Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions docs/operator-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ fixture; it is not a complete proof of production safety.
For the separate legacy-data maintenance procedure, use the [legacy leakage
scrub runbook](operators/legacy-leakage-scrub-v1.md). It requires a dedicated
admin PostgreSQL connection and a private 32-byte HMAC key. The PostgreSQL
proof, Redis credential-revocation proof, and complete cross-sink proof are
separate gates; do not treat one as evidence for the others.
scrub proof, Redis purge proof, and Redis ACL proof are each necessary, but
none alone proves that the supported production sinks share one safe boundary.
The mandatory combined cross-sink proof below is a separate release gate.

### Redis task-event cutover

Expand Down Expand Up @@ -377,8 +378,34 @@ FORGE_S4_REDIS_ACL_TEST_REQUIRED=1 FORGE_S4_REDIS_ACL_DESTRUCTIVE_TEST=1 \
# S4_REDIS_ACL_LEGACY_REVOKED_OK
```

These are separate gates. Passing them does not claim the deferred complete
cross-sink production proof.
These are separate gates. Passing them does not replace the mandatory combined
cross-sink proof below.

#### Combined cross-sink production proof

The mandatory combined CI proof is
`cross-sink-production-sentinel.postgres-redis.test.ts`. It must pass exactly
1/1 and emit `S4_CROSS_SINK_PRODUCTION_SENTINEL_OK`. It composes the real
production writers, readers, routes, projections, and scrub adapters against
disposable PostgreSQL and Redis services, then checks the supported sink set
collectively:

- canonical `tasks.prompt` authorization;
- task API projections;
- logs and export;
- Server-Sent Events live, snapshot, and replay;
- Redis history, sequence, and live data;
- worker diagnostics;
- the scrubbed database inventory;
- the signed producers-disabled receipt;
- zero-scan and reappearance checks; and
- legacy Redis ACL revocation.

This is exact hosted disposable-service release evidence. It is not a
production deployment, not proof for arbitrary future producers or sinks, and not proof of correctness. Any new producer or sink must extend the proof
corpus and inspection before relying on this marker. It does not imply that
the future specialist, ACP, or three-lease execution lifecycle is implemented
or enabled.

#### Rollback-safe handling

Expand Down
33 changes: 30 additions & 3 deletions docs/operators/legacy-leakage-scrub-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,35 @@ The test must report all tests passed with zero skips and emits these markers:

That proof covers the PostgreSQL authorization, row/checkpoint compare-and-set,
resume, reappearance, and protected-artifact link-race contracts. It does not
claim the separate Redis credential-revocation/namespace proof or the complete cross-sink production proof.
Those are later gates and must be run and reviewed separately.
claim the separate Redis credential-revocation/namespace proof or the combined
cross-sink production boundary by itself. Those are separate gates and must be
run together through the mandatory proof below.

## Combined cross-sink production proof

The mandatory combined CI proof is
`cross-sink-production-sentinel.postgres-redis.test.ts`. It must pass exactly
1/1 and emit `S4_CROSS_SINK_PRODUCTION_SENTINEL_OK`. It composes the supported
Comment on lines +204 to +206

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add an executable path for the combined-proof gate

When an operator tries to reproduce this newly mandatory gate, the documented filename is insufficient: a direct Vitest run exits successfully with the only test skipped unless destructive mode and three dedicated service URLs are configured, while the disposable database setup and exact 1/1/marker validation exist only inside .github/workflows/web-ci.yml. Include the safe setup and checked invocation, add a wrapper command, or link directly to the relevant workflow step so this release gate is operable from the runbook.

AGENTS.md reference: AGENTS.md:L155-L165

Useful? React with 👍 / 👎.

production writers, readers, routes, projections, and scrub adapters against
disposable PostgreSQL and Redis services and verifies the supported sink set
collectively:

- canonical `tasks.prompt` authorization;
- task API projections;
- logs and export;
- Server-Sent Events live, snapshot, and replay;
- Redis history, sequence, and live data;
- worker diagnostics;
- the scrubbed database inventory;
- the signed producers-disabled receipt;
- zero-scan and reappearance checks; and
- legacy Redis ACL revocation.

This is exact hosted disposable-service release evidence, not a production
deployment, not proof for arbitrary future producers or sinks, and not proof of correctness. New producer or sink surfaces must extend the proof corpus and
inspection before they can rely on this marker. It does not imply that the
future specialist, ACP, or three-lease execution lifecycle is implemented or
enabled.

## Redis ACL and protected-mode cutover

Expand Down Expand Up @@ -277,7 +304,7 @@ FORGE_S4_REDIS_ACL_TEST_REQUIRED=1 FORGE_S4_REDIS_ACL_DESTRUCTIVE_TEST=1 \
# S4_REDIS_ACL_LEGACY_REVOKED_OK
```

These are separate gates and do not claim the deferred complete cross-sink
These are separate gates and do not replace the mandatory combined cross-sink
production proof. Before activation, keep the database mode legacy and do not
inject the dedicated URLs into running legacy processes while investigating.
Creating the ACL users and storing their secrets out of process does not select
Expand Down
25 changes: 23 additions & 2 deletions web/__tests__/legacy-leakage-scrub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,26 @@ describe('legacy leakage CLI and operator guide', () => {
expect(envExample).toContain(envName)
}
expect(runbook).toContain('Redis credential-revocation/namespace proof')
expect(runbook).toContain('complete cross-sink production proof')
expect(runbook).not.toContain(['deferred complete', 'cross-sink production proof'].join(' '))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the stale-claim check whitespace-tolerant

When Markdown wraps any part of the prohibited phrase onto another line, this exact not.toContain check passes even though the runbook again describes the cross-sink proof as deferred. The previous assertion tolerated whitespace, so normalize the prose or use a \s+-based negative match to preserve the intended regression coverage.

Useful? React with 👍 / 👎.

for (const combinedProofContract of [
'mandatory combined CI proof',
'cross-sink-production-sentinel.postgres-redis.test.ts',
'S4_CROSS_SINK_PRODUCTION_SENTINEL_OK',
'canonical `tasks.prompt` authorization',
'task API projections',
'logs and export',
'Server-Sent Events live, snapshot, and replay',
'Redis history, sequence, and live data',
'worker diagnostics',
'scrubbed database inventory',
'signed producers-disabled receipt',
'zero-scan and reappearance checks',
'legacy Redis ACL revocation',
'not proof for arbitrary future producers or sinks',
'not proof of correctness',
]) {
expect(runbook).toContain(combinedProofContract)
}
expect(runbook).toContain('schemaVersion: 2')
expect(runbook).toContain('sentinelSetFingerprint')
expect(runbook).toContain('legacy_task_log_unavailable')
Expand Down Expand Up @@ -1130,7 +1149,9 @@ forge:task-events:v2:* keys.`
'S4_REDIS_ACL_DENIALS_OK',
'S4_REDIS_ACL_LEGACY_REVOKED_OK',
]) expect(runbook).toContain(proofContract)
expect(runbook).toMatch(/deferred complete cross-sink\s+production proof/)
expect(runbook).not.toContain(['deferred complete', 'cross-sink production proof'].join(' '))
expect(operatorGuide).toContain('cross-sink-production-sentinel.postgres-redis.test.ts')
expect(operatorGuide).toContain('S4_CROSS_SINK_PRODUCTION_SENTINEL_OK')
expect(operatorGuide).toContain('database-authoritative S4 runtime mode')
expect(operatorGuide).toMatch(/Changing environment values\s+alone cannot flip the mode/)
for (const aclToken of [
Expand Down
Loading