> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/governance/certification/operate-certification-services.md).

# Operate certification services

How the certification subsystem is put together — its own service, database and queues, the ephemeral preview store, what schedules a certification, and the retention position you inherit.

## What this is, and when you need it

Certification does not run inside the rest of OpenIAM. It is a separate service with its own database, its own queues and its own short-lived stores, and every certification screen you open is a message sent to it and a reply waited for. That architecture is invisible while it works and unmissable when it does not.

Read this page when you are operating the subsystem rather than configuring a campaign: when you are planning backups, when you need to know where certification data actually lives, or before you write a report against it from outside the product — certification tables are **not** in the `openiam` schema and a join to `USERS` or `ROLE` is a cross-database join. When a campaign has already stopped moving, go straight to [Diagnose a stalled campaign](/administration-guide/governance/certification/diagnose-a-stalled-campaign.md), which is the ordered procedure. Building a campaign is [Plan and scope a campaign](/administration-guide/governance/certification/plan-and-scope-a-campaign.md); deciding and closing one is [Operate a live campaign](/administration-guide/governance/certification/operate-a-live-campaign.md).

The one risk specific to this page: **dropping or restoring the `certification` database alone desynchronizes it from the Activiti process variables that hold campaign and reviewer ids.** Back up and restore `certification`, `activiti` and `openiam` as one set.

## Where certification work executes

Certification is one Spring Boot service, `certification-manager`. It owns the whole subsystem except the reviewer workflow, which stays in Activiti inside the `workflow` service.

Nothing calls it in-process. Every read and write from Webconsole, SelfService and the ESB is a **synchronous RabbitMQ request/reply** on the `CertificationQueue` queue, vhost `openiam_am`. Which operation a message asks for is carried in its `API_NAME` header, one of 81 values from `GET_BY_ID` to `FIND_CAMPAIGN_USER_SUMMARIES`; you can read that header on a message in the RabbitMQ management UI when you are diagnosing a backlog. The count grows release to release — treat it as an indication of scale, not a checksum.

The practical consequence: **with `certification-manager` down, the certification screens fail rather than degrade.** They wait for a reply until `org.openiam.mq.broker.reply.timeout` expires, which the shipped deployment sets to `120000` ms, then surface an error. There is no local fallback path.

Long work does not run on the reply thread. Inside the service:

| Work                                        | Where it runs                                                                                  | Bound by                                                                                                  |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Preview compute (`START_PREVIEW`)           | A fixed background pool named `certificationPreviewExecutor`, threads prefixed `cert-preview-` | `org.openiam.certification.preview.executor.max.pool.size` (**4**), `...executor.queue.capacity` (**50**) |
| Launch from preview (`LAUNCH_FROM_PREVIEW`) | The same pool                                                                                  | as above                                                                                                  |
| Report chunks (`PROCESS_REPORT_CHUNK`)      | Its own queue and consumers, so it does not compete with ordinary reads and writes             | `CertificationReportChunkQueue`                                                                           |
| Risk score write-back (`SCORE_CHANGED`)     | `RiskScoreChangeQueue` on the **common** vhost                                                 | consumer presence in `certification-manager`                                                              |
| Nightly risk convergence                    | A scheduled job inside the service, **not** a batch task                                       | `org.openiam.cert.risk.reconcile.cron`, default `0 30 3 * * *`                                            |
| Reviewer tasks, escalation, completion      | Activiti in the `workflow` service                                                             | the reviewer workflow itself                                                                              |

When the pool and its queue are both full, OpenIAM does not queue the request any further — it fails the preview outright with a capacity error. That is the one case where a preview never starts at all.

The three queues by name, on the vhosts shown:

| Queue                           | vhost            | Consumed by                                   | Carries                                     |
| ------------------------------- | ---------------- | --------------------------------------------- | ------------------------------------------- |
| `CertificationQueue`            | `openiam_am`     | `certification-manager`                       | Every certification request and its reply   |
| `CertificationReportChunkQueue` | `openiam_am`     | `certification-manager` (competing consumers) | One message per 5,000-item report page      |
| `RiskScoreChangeQueue`          | `openiam_common` | `certification-manager`                       | `SCORE_CHANGED` batches from `risk-manager` |

{% hint style="info" %}
A queue called `AccessReviewQueue` also exists on `openiam_am` and **nothing consumes it**. An idle queue with that name, showing zero consumers and zero messages, is expected — it is not the certification queue and its idleness is not a fault. Watch `CertificationQueue` instead.
{% endhint %}

## The one extension point: the certification helper

Certification resolves the in-scope user population through a helper that pages users, and you can replace it with your own Groovy. This is the only configurable extension point in the subsystem, and it is configured by property:

| Property                                                         | Shipped value                                         | Category |
| ---------------------------------------------------------------- | ----------------------------------------------------- | -------- |
| `org.openiam.activiti.access.certification.helper.groovy.script` | `/bpm/certification/CustomCertificationHelper.groovy` | Workflow |

The shipped script extends the helper base class, and the import moved in 2026.6.1.0 — a script written against the older package no longer resolves:

{% code overflow="wrap" expandable="true" %}

```groovy
package org.openiam.esb.core.batch.tasks

import org.openiam.certification.initializer.CertificationHelper
import org.openiam.dto.User
import org.openiam.idm.searchbeans.UserSearchBean

class CustomCertificationHelper extends CertificationHelper {
    @Override
    List<User> getData(UserSearchBean userSearchBean, int from, int size) {
        super.getData(userSearchBean, from, size)
    }
}
```

{% endcode %}

{% hint style="warning" %}
A site copy of this script that still imports the pre-2026.6.1.0 package `org.openiam.batch.manager.initializer.CertificationHelper` — or the older `AccessCertificationHelper` — fails to instantiate after an upgrade, and OpenIAM **swallows the failure**. It logs `Cannot instantiate script: <path>. Using default helper logic` and silently continues with the default scope resolution. Your custom scoping stops applying and nobody is told. There is no screen that shows whether the override loaded; the log line is the only signal, so search the `certification-manager` log for that string after every upgrade.
{% endhint %}

The helper's page size is `org.openiam.access.certification.init.recommended.search.size`, default **500**. It carries a built-in default, so it works without a `SYS_PROP` row and you will not find it listed under **Administration → System Configuration** unless someone has added it.

{% hint style="info" %}
A near-identical key, `org.openiam.certification.init.recommended.search.size`, also ships with the service but **nothing reads it**. The live key keeps the `access.` segment. Setting the short form changes nothing, and nothing warns you that it was ignored — if a page-size change had no effect, check which of the two names you set.
{% endhint %}

## The separate database

`certification-manager` opens its own connection pool against its own database. Four keys define it:

| Key                                        | Shipped value                                                                                                                                                           |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jdbc.certification.url`                   | `jdbc:mysql://${jdbc.host}:${jdbc.port}/certification?autoReconnect=true&useUnicode=true&characterEncoding=utf8&connectionCollation=utf8_general_ci&serverTimezone=UTC` |
| `certification.databaseSchema.name`        | `certification`                                                                                                                                                         |
| `vault.secret.certification.jdbc.username` | from Vault; the shipped user is `CERTIFICATION`                                                                                                                         |
| `vault.secret.certification.jdbc.password` | from Vault                                                                                                                                                              |

Under MSSQL and Oracle the shipped `certification.databaseSchema.name` is `dbo` or `CERTIFICATION` rather than a separate database, so on those platforms certification tables sit alongside the others and the "separate database" framing here is a schema separation instead.

Where these values are set, and how to change them, is deployment work: it means editing the property layer on the server and restarting the service, which is the [Installation Guide](/installation/installation.md)'s territory rather than this one. What you will notice from the Webconsole is only the failure — a service that will not start and logs a datasource error, and certification screens that error rather than degrade.

Two behaviours of this pool are worth knowing because they only affect certification:

* **Inserts are batched.** A launch writes `ACCESS_REVIEW_ITEM` rows in batches rather than one statement per row. That is why a launch's row count climbs in steps when you watch it.
* **The connection URL is rewritten at startup.** For a MySQL or MariaDB URL, OpenIAM appends `rewriteBatchedStatements=true` if it is not already present, so the URL the pool actually opens is not byte-identical to the one configured. Do not "fix" that discrepancy. You cannot see the rewritten URL from the Webconsole; the deployment owner can see it in the service's startup log.

The `certification` database is migrated independently of `openiam`, on its own version sequence, and it has its own `OPENIAM_VERSION` table. The release-by-release sequence, the break-glass query that reads it, and every table and column are in [Certification database tables](/administration-guide/reference/certification-tables.md). Applying those migrations is deployment work; the symptom you will see if it has not happened is unambiguous — the service starts, and then every certification query fails complaining about an unknown table.

{% hint style="warning" %}
Schedule the 2026.7.2.0 upgrade for a low-traffic window **with no campaign launch in flight**, and tell whoever runs it why: it builds four secondary indexes on `ACCESS_REVIEW_ITEM`, `ACCESS_REVIEW_ITEM_AUDIT` and `CAMPAIGN_REVIEWERS`. The builds are online and do not lock the tables, but on a large `ACCESS_REVIEW_ITEM` they take time and temporary disk proportional to table size.
{% endhint %}

### The migration gate

The one-shot import from the legacy `openiam` schema is off in the shipped build:

| Property                                         | Shipped value |
| ------------------------------------------------ | ------------- |
| `org.openiam.certification.migrate-from-openiam` | `false`       |

`true` is required exactly once, for the upgrade that introduces `certification-manager`. With the default value the migration does not merely skip — the read-only connection to the legacy database is never opened at all, so a wrong password on the old schema cannot break a normal start. The table rename map is in [Certification database tables](/administration-guide/reference/certification-tables.md#the-legacy-rename-map), and the migration's guarantees are on [The certification model](/administration-guide/governance/certification/certification-model.md).

You cannot read this property's effective value from the Webconsole. What you can confirm is its consequence: with it `false`, the `certification-manager` log contains no migration lines and the legacy database shows no connection from the service.

`batch-task-manager` has the exact same pattern under a different key, `org.openiam.batchtasks.migrate-from-openiam` (also `false`). Do not confuse them.

## The preview store is ephemeral, and it is not reindexable

A preview writes nothing to the certification database. It lives in three OpenSearch indexes and two Redis keys, and all five are disposable — losing them costs you the previews in flight and nothing else, and excluding them from your snapshots is correct. The indexes, their fields and the two Redis key families are in [Certification database tables](/administration-guide/reference/certification-tables.md#the-preview-store).

The consequence worth carrying: **launch is a read then a write with no recompute.** The included rows in `certification_preview_item` already carry the per-entitlement snapshot that promotion copies straight onto `ACCESS_REVIEW_ITEM`, which is why a preview that has gone stale cannot simply be launched with fresher data — it has to be re-run. The three shapes staleness takes are on [Diagnose a stalled campaign](/administration-guide/governance/certification/diagnose-a-stalled-campaign.md#how-a-stale-preview-presents).

## What schedules a certification

**No shipped `BATCH_CONFIG` row schedules certification.** A schedule is created per certification, when you save one with a **Scheduled Interval**. OpenIAM looks for a `BATCH_CONFIG` row whose `PARAM_1` is the certification's id and creates or updates that single row:

| Column               | Value                                                           |
| -------------------- | --------------------------------------------------------------- |
| `NAME`               | The certification's name                                        |
| `PARAM_1`            | The `CERTIFICATION_ID` — **this is the join key**, not the name |
| `SPRING_BEAN`        | `accessCertificationInitializer`                                |
| `SPRING_BEAN_METHOD` | `initializeAccessCertification`                                 |
| `ENABLED`            | `Y` when `CERTIFICATION.STATUS` is `ACTIVE`, otherwise `N`      |
| `CRON_EXPRESSION`    | Derived from `START_DATE` and `SCHEDULE_TYPE`                   |
| `RUN_ON`             | The certification's `START_DATE`                                |

The cron is generated, not entered, with `<d>` the day of month and `<m>` the month of `START_DATE`:

| **Scheduled Interval** | Generated cron    |
| ---------------------- | ----------------- |
| `ANNUALLY`             | `0 0 0 <d> <m> ?` |
| `SEMI_ANNUALLY`        | `0 0 0 <d> 1/6 ?` |
| `QUARTERLY`            | `0 0 0 <d> 1/3 ?` |
| `MONTHLY`              | `0 0 0 <d> * ?`   |

Any other interval is rejected. Deleting the certification deletes every `BATCH_CONFIG` row with that `PARAM_1`, tears down the preview footprint, and asks Activiti to delete its reviewer tasks with the reason `Configration of access certification was deleted` — that is the product's spelling, and it is what you will see in the workflow history, so search for it as written.

**Confirm the schedule is wired** by finding that `BATCH_CONFIG` row under **Administration → Batch Tasks** — the certification's name will be on it, with `ENABLED = Y` if the certification is `ACTIVE`.

What the scheduled run does is narrower than the name suggests: it starts a preview with no validity window and stops there. **A scheduled certification produces a preview and waits for a human to promote it.** Nothing is generated and no reviewer is notified until someone launches from that preview.

The two batch tasks that actually matter to a live campaign are `REQUEST_REMINDERS` and `REQUEST_ESCALATION`, both shipped `ENABLED='N'` — see [Configure the review workflow](/administration-guide/governance/certification/configure-the-review-workflow.md). `CLEANUP_CSV` also ships disabled and is what ages out generated report files.

### Withdrawn task ids

Five batch task ids were seeded by earlier releases and **deleted by later migrations**. None exists in a current install:

`ACC_CERT_GEN_REPORT` · `ACC_NTFC_REMINDER_BT_` · `ATTESTATION` · `CANCEL_UAR_CAMPAIGN_REQ` · `GROUP_ATTESTATION`

A runbook that tells you to enable `ACC_NTFC_REMINDER_BT_` for reviewer reminders, or `ACC_CERT_GEN_REPORT` to produce a campaign report, is describing a removed task. Reminders are `REQUEST_REMINDERS`; reports generate themselves (see [Campaign history and evidence](/administration-guide/governance/certification/campaign-history-and-evidence.md)); campaign cancellation is **Delete campaign** on the campaign's **Dashboard** tab. The live inventory is [Shipped batch tasks](/administration-guide/reference/shipped-batch-tasks.md).

## A known issue: the sign-off gate has no caller

First, the good news, because this used to be a much bigger problem. **The gate no longer applies to ordinary campaigns.** When a campaign's last item settles, the status it takes is decided like this:

| Condition                                                 | Status              |
| --------------------------------------------------------- | ------------------- |
| Every request expired without review                      | `EXPIRED`           |
| At least one request expired without review               | `PARTIALLY_EXPIRED` |
| Every item was auto-certified — no human decided anything | `AWAITING_SIGN_OFF` |
| Anything else — **at least one human decision**           | `COMPLETED`         |

One human decision anywhere in the campaign is treated as the attestation, and the campaign closes directly to `COMPLETED`. So a normally reviewed campaign is not affected by anything below.

{% hint style="danger" %}
**A campaign settled entirely by automation reaches `AWAITING_SIGN_OFF`, and there is nothing in the product that closes it.**

Sign-off itself is implemented, and so is the `SIGN_OFF_CAMPAIGN` operation that would trigger it: it would set `STATUS = COMPLETED`, `SIGNED_OFF_BY`, `SIGN_OFF_DATE` and `ACTUAL_COMPLETED_DATE`, and reopen any items the signer rejected. **Nothing invokes it.** There is no Webconsole route and no SelfService screen a campaign owner can use to sign off — the reviewer app renders `AWAITING_SIGN_OFF` only as a status label. `AWAITING_SIGN_OFF` is therefore where a fully auto-certified campaign stops.

This is not something you can confirm or refute from the console — the absence of a caller is not observable from a screen. Check your release notes before building a control that depends on either behaviour, and raise it with support if your release notes claim sign-off is available.

You are most likely to hit this on a campaign with a **low membership risk threshold and a generous auto-certify maximum**, where the automation rules settle every item before a reviewer opens anything. If that is not what you intended, the campaign scope is the thing to fix.

The operational workaround is to stop treating `STATUS` as the completion signal:

* **`CAMPAIGN.ACTUAL_COMPLETED_DATE` is set when the last item settles**, not at sign-off. Use it, together with `COMPLETED_COUNT = TOTAL_COUNT`, as your "review finished" test.
* **The complete report is already generated and already accurate.** It fires on `completedCount == totalCount`, before any sign-off.
* **`UAR_CAMPAIGN_COMPLETED` is already sent** to the campaign managers.
* Expect `SIGNED_OFF_BY` and `SIGN_OFF_DATE` to be `NULL`, and treat `AWAITING_SIGN_OFF` as a terminal state in dashboards and queries.

A manual `UPDATE CAMPAIGN SET STATUS = 'COMPLETED'` is the obvious temptation and it is the wrong break-glass. Sign-off does more than set a status: it also reopens the items the signer rejected and adjusts `COMPLETED_COUNT`. A hand-set status skips all of that, produces no audit record of who signed off, and leaves you with a campaign whose evidence says it completed and whose item rows say nobody decided. If a report insists on `COMPLETED`, change the report to accept `AWAITING_SIGN_OFF` instead.
{% endhint %}

## Backup and retention

**Back up three databases as one set.** `certification` holds the campaign and item rows; `activiti` holds the in-flight reviewer processes, whose process variables carry campaign and reviewer ids; and `openiam` holds the users, roles and groups those ids point at. Restoring `certification` to an earlier point than `activiti` leaves live reviewer tasks referencing items that no longer exist. The migration runner preserves primary keys for exactly this reason — treat the same constraint as a backup rule.

**Nothing prunes certification data.** There is no retention job for `CERTIFICATION`, `CAMPAIGN` or `ACCESS_REVIEW_ITEM`: no `BATCH_CONFIG` row you can enable, no internal sweep, and no `org.openiam.audit.log.prune.days.*` equivalent. A quarterly campaign over 50,000 items adds 50,000 `ACCESS_REVIEW_ITEM` rows plus one `ACCESS_REVIEW_ITEM_AUDIT` row per reviewer action per item, forever, and that is deliberate — it is the audit evidence. Size the `certification` database for accumulation, not for steady state, and plan an archive strategy rather than a delete strategy.

**The only "cleanup" is destructive.** **Delete campaign** cascades to `ACCESS_REVIEW_ITEM`, `ACCESS_REVIEW_ITEM_AUDIT`, `ACCESS_REVIEW_ITEM_SOD_VIOLATION`, `ACCESS_REVIEW_ITEM_CUR_REV`, `CAMPAIGN_STEP`, `CAMPAIGN_REVIEWERS` and `CAMPAIGN_PREVIEW_EXCLUSION`, and deleting a `CERTIFICATION` cascades to every campaign under it. Export the complete report and the campaign-history views first — see [Campaign history and evidence](/administration-guide/governance/certification/campaign-history-and-evidence.md).

**Report files are separate from the database, and they do grow.** Generated CSVs live in `<confpath>/upload`, with part files under `<confpath>/upload/.parts`. That directory must be a **shared volume** across every node that builds report chunks, or assembly cannot find the parts; and `CLEANUP_CSV` (cron `0 0 1 * * ?`) ships disabled, so nothing ages the files out until you enable it.

## Verification

| Claim                                     | Evidence                                                                                                                                                                                                                                                        |
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The service is up and scheduling          | `${confpath}/health/certification-manager.simple.health` reads `UP` and its mtime is within 30 s                                                                                                                                                                |
| Its own database is migrated              | `SELECT ID, VERSION FROM certification.OPENIAM_VERSION` includes the running release                                                                                                                                                                            |
| It is using its own datasource            | The `certification` database shows live connections from the configured user (`SELECT USER, DB FROM information_schema.PROCESSLIST WHERE DB = 'certification'`), and a certification screen loads                                                               |
| The legacy migration is off               | `org.openiam.certification.migrate-from-openiam` is `false`; the `certification-manager` log shows no migration lines and the legacy database shows no connection from the service                                                                              |
| A custom helper script is actually in use | **Absence** of `Cannot instantiate script: … Using default helper logic` in the `certification-manager` log for `/bpm/certification/CustomCertificationHelper.groovy`. There is no screen that confirms it positively — the missing log line is the only signal |
| A scheduled certification is wired        | A `BATCH_CONFIG` row with `PARAM_1 = <CERTIFICATION_ID>`, `SPRING_BEAN = 'accessCertificationInitializer'`, `ENABLED = 'Y'` and the generated cron                                                                                                              |
| Your backup covers governance history     | The backup set includes `certification` and `activiti`, not `openiam` alone                                                                                                                                                                                     |

## When it goes wrong

Stalls — a frozen preview, a launch that never finishes, reviewers with no task — are on [Diagnose a stalled campaign](/administration-guide/governance/certification/diagnose-a-stalled-campaign.md#when-it-goes-wrong). These are the configuration and deployment causes.

| Symptom                                                       | Cause                                                                                                                                                                    | Fix                                                                                                                                                                                                                      |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Service will not start, complains about the datasource        | `jdbc.certification.url` or `certification.databaseSchema.name` is missing, or the Vault secrets `vault.secret.certification.jdbc.username` / `.password` are unresolved | All four must be present. Setting them is deployment work: [Installation Guide](/installation/installation.md)                                                                                                           |
| Service starts but every query fails on unknown table         | The `certification` schema was never migrated                                                                                                                            | The migrations must be applied — [Installation Guide](/installation/installation.md). Verify with the break-glass `certification.OPENIAM_VERSION` query                                                                  |
| Upgrade left the new schema empty                             | `org.openiam.certification.migrate-from-openiam` was left `false` through the introducing upgrade                                                                        | Set it `true` for one start — it is safe to leave on, because the migration no-ops once `CERTIFICATION` has rows. Changing it means a property change and a restart: [Installation Guide](/installation/installation.md) |
| Custom scope logic stopped applying                           | The Groovy helper still imports the pre-2026.6.1.0 package `org.openiam.batch.manager.initializer.CertificationHelper`; the failure is logged and swallowed              | Re-point the import at `org.openiam.certification.initializer.CertificationHelper` in Groovy Manager and confirm the `Cannot instantiate script` line stops appearing                                                    |
| Page size property has no effect                              | You set `org.openiam.certification.init.recommended.search.size`, which nothing reads                                                                                    | Use `org.openiam.access.certification.init.recommended.search.size`                                                                                                                                                      |
| A schedule fired but no campaign appeared                     | A scheduled run starts a preview and stops; promotion is a human act                                                                                                     | Promote it from the **Preview** tab inside the freshness window                                                                                                                                                          |
| A campaign sits in `AWAITING_SIGN_OFF` forever                | Nothing in this build invokes sign-off, so review activity alone never sets `COMPLETED`                                                                                  | Expected — use `ACTUAL_COMPLETED_DATE` and the complete report; see the danger note above                                                                                                                                |
| Renaming a certification orphaned its schedule in reports     | `BATCH_CONFIG.NAME` is a copy taken at save; only `PARAM_1` links back                                                                                                   | Join on `PARAM_1 = CERTIFICATION_ID`                                                                                                                                                                                     |
| An external report shows suspiciously perfect coverage        | It reads `ACCESS_REVIEW_ITEM` only; exclusions are in `CAMPAIGN_PREVIEW_EXCLUSION`                                                                                       | Union both tables                                                                                                                                                                                                        |
| A join from `CAMPAIGN` to `ROLE` or `USERS` returns nothing   | Different databases                                                                                                                                                      | Use the snapshot columns on `ACCESS_REVIEW_ITEM`, or a cross-database join                                                                                                                                               |
| A query selects from `CERTIFICATION_RISK_TYPES` and fails     | The table was dropped in 2026.7.1.0                                                                                                                                      | Read `CERTIFICATION.RISK_SCORE_THRESHOLD` instead                                                                                                                                                                        |
| Index-building migration ran long and blocked a launch        | The 2026.7.2.0 upgrade builds four indexes on `ACCESS_REVIEW_ITEM`                                                                                                       | Schedule that upgrade for a low-traffic window with no launch in flight                                                                                                                                                  |
| `<confpath>/upload` fills the disk                            | `CLEANUP_CSV` ships `ENABLED='N'`                                                                                                                                        | Enable it (cron `0 0 1 * * ?`)                                                                                                                                                                                           |
| A restored system has live reviewer tasks pointing at nothing | `certification` was restored to a different point than `activiti`                                                                                                        | Restore the three databases as one set                                                                                                                                                                                   |

## Related

* [Diagnose a stalled campaign](/administration-guide/governance/certification/diagnose-a-stalled-campaign.md) — the ordered procedure when something has stopped
* [Certification database tables](/administration-guide/reference/certification-tables.md) — every table, every preview field, the migration sequence and the rename map
* [The certification model](/administration-guide/governance/certification/certification-model.md) — the objects in those tables
* [Campaign history and evidence](/administration-guide/governance/certification/campaign-history-and-evidence.md) — the chunked report build, `<confpath>/upload` and `CLEANUP_CSV`
* [Operate a live campaign](/administration-guide/governance/certification/operate-a-live-campaign.md) — the sign-off gate from the campaign side
* [Shipped batch tasks](/administration-guide/reference/shipped-batch-tasks.md) — `REQUEST_REMINDERS`, `REQUEST_ESCALATION`, `CLEANUP_CSV` and their shipped enabled state

*Applies to OpenIAM 2026.9.1. Last reviewed 14 September 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/governance/certification/operate-certification-services.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
