Activate the Bulk PDF notifier authority¶
The Bulk PDF notifier authority (BulkPdfNotifierAuthority) is default-off. This guide lists the
chart values an environment sets in cluster-gitops to turn it on, the zero-usage proof it
requires, and the order in which it and featureFlags.bulkPdfUpload are enabled.
Changing these values is a GitOps change to environment configuration. Nothing in the SyRF repository activates an environment, and a merged PR does not prove one is ready. The other activation gates in the durable-capture evidence and in syrf#3168 still apply.
What each chart renders¶
| Values key | API | Project Management | Identity |
|---|---|---|---|
bulkPdfNotifierAuthority.enabled |
yes | yes | yes |
bulkPdfNotifierAuthority.zeroUsageProof.* |
yes | yes | yes |
bulkPdfNotifierAuthority.clients[] |
clientId, environmentRoot, cleanupAuthorityId |
no | same, plus clientSecret by Secret reference |
bulkPdfNotifierAuthority.revokedClientIds[] |
yes | no | yes |
While enabled is false the charts render no SYRF__BulkPdfNotifierAuthority__* variable, so
the hosts keep their disabled defaults. The one exception is revokedClientIds, which renders
regardless of enabled: Identity deletes revoked notifier clients on every start, and revoking is
how an activated environment is turned back off.
Rendering fails if an enabled client omits any field. Identity never takes a literal client secret: each client names a Kubernetes Secret and the key inside it.
Prerequisites¶
- The API has a complete OpenIddict introspection client:
identityService.baseUrl(an absolute http(s) URL),identityService.audience,identityService.clientSecretNameand, if notsyrf-api,identityService.clientId. With the authority enabled, the API refuses to start and names every missing setting. bulkPdfStorage.environmentRoot(or the preview root derived fromsyrf.prNumber) is the root the clients will name. Every client in one deployment uses the same single root, andproductionis rejected.- A Kubernetes Secret holds each notifier client secret for Identity. Its name and key go in the values; the secret material never does.
featureFlags.bulkPdfUploadis stillfalse.
Values to set¶
Set the same enabled and zeroUsageProof on all three services. Set clients on API and
Identity (Identity also needs clientSecret).
bulkPdfNotifierAuthority:
enabled: true
clients:
- clientId: bulk-pdf-notifier-staging # OpenIddict client the s3-notifier uses
clientSecret: # Identity chart only
secretName: bulk-pdf-notifier-staging
key: clientSecret
environmentRoot: staging # single root for the whole deployment
cleanupAuthorityId: 7b0c6f55-4d4c-4d41-9a55-2f2a1b8d7c01
revokedClientIds: []
zeroUsageProof:
proofId: 0f4d2a9e-3c1b-4b8e-9d7a-5e6f7a8b9c0d # new GUID per proof
observedAt: "2026-09-16T09:00:00Z"
expiresAt: "2026-09-16T09:45:00Z" # later than observedAt, at most 1 hour after it
activationRecordedAt: "2026-09-16T09:10:00Z" # see "Record activation" below
releaseRecordCount: 0
storageBindingCount: 0
quarantineFenceCount: 0
queueMessageCount: 0
embeddedJobCount: 0
storageObjectCount: 0
multipartUploadCount: 0
These values become SYRF__BulkPdfNotifierAuthority__Enabled,
SYRF__BulkPdfNotifierAuthority__Clients__<n>__{ClientId,ClientSecret,EnvironmentRoot,CleanupAuthorityId},
SYRF__BulkPdfNotifierAuthority__RevokedClientIds__<n> and
SYRF__BulkPdfNotifierAuthority__ZeroUsageProof__<Field>.
The zero-usage proof¶
The proof shows that the environment holds no Bulk PDF state the authority could take over. The hosts accept only a proof in which every counter is explicitly zero. An omitted counter does not render and binds as unset, which fails the proof, so every counter must be present.
Observe each count for the exact environment root, all within one window that starts at
observedAt:
| Counter | What it counts |
|---|---|
releaseRecordCount |
Notifier release records held by Project Management |
storageBindingCount |
Bulk PDF upload storage bindings |
quarantineFenceCount |
Bulk PDF upload quarantine fences |
queueMessageCount |
Messages on the Bulk PDF notifier queues, visible and in flight |
embeddedJobCount |
Bulk PDF upload jobs embedded in projects |
storageObjectCount |
Object versions under the environment root's reserved Bulk PDF prefix |
multipartUploadCount |
Incomplete S3 multipart uploads under that prefix |
No script produces these counts yet. Record how each was observed with the change.
If any count is not zero, do not activate. The authority is a zero-only contract: an environment that already holds Bulk PDF state needs a separately designed migration. The hosts reject any non-zero counter, and Helm renders large numbers in scientific notation that does not bind at all.
The hosts check the proof at startup:
expiresAtmust be later thanobservedAtand at most one hour after it.- Startup succeeds while the proof is fresh (
observedAt≤ now <expiresAt), or at any later time onceactivationRecordedAtis recorded.
Record activation¶
Upload admission needs a recorded activation, not just a fresh proof. Set
activationRecordedAt to a time that is:
- at or after
observedAt, - before
expiresAt, and - not in the future when the services start.
Commit it while the proof is still fresh. The recorded proof then survives restarts after
expiresAt. If the window closes before activation is recorded, take a new proof with a new
proofId.
Order of operations¶
- Confirm the prerequisites, with
featureFlags.bulkPdfUploadstillfalse. - Take the zero-usage proof and commit the
bulkPdfNotifierAuthorityvalues for API, Project Management and Identity, withactivationRecordedAtinside the proof window. Let ArgoCD sync. - Check that API, Project Management and Identity start, and that Identity seeded the notifier clients.
- Only then set
featureFlags.bulkPdfUpload: truein a separate change.
Do not reverse this order. API and Project Management refuse to start with uploads enabled and the authority disabled. Completed uploads record cleanup obligations that only the authority can discharge, and once uploads exist the zero-usage proof can no longer pass.
Turning the authority off¶
There is no designed deactivation procedure yet. Once uploads exist, their cleanup obligations can
only be discharged by an active authority, so disabling it strands them; plan any rollback in
syrf#3168 first. The mechanics available today: setting enabled: false stops rendering the
clients and proof, and listing notifier client IDs in revokedClientIds makes Identity delete those
OpenIddict clients and the API refuse their tokens. A revoked client ID cannot also be an active
client.
Related¶
.claude/rules/pdf-agent.md: notifier authority invariants- Bulk PDF durable capture evidence: other activation gates
- Extend the env-mapping schema: list bindings (
listPath)