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
46 changes: 43 additions & 3 deletions .github/workflows/deploy-cloudflare-worker.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: deploy-cloudflare-worker

# Source merges are not deployment authorisation. Keep publication rollout
# manual while the schema-first staging, drain and canary gates are outstanding.
# Source merges are not deployment authorisation. Production deployment remains
# manual and requires exact release identity plus fail-closed canary controls.
on:
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -79,4 +79,44 @@ jobs:
{ mode: 0o600 }
);
NODE
npx wrangler deploy --tag "${{ github.sha }}" --secrets-file "$secrets_file"
npx wrangler deploy --env="" --tag "${{ github.sha }}" --secrets-file "$secrets_file"
- name: Verify the exact fail-closed canary release
env:
EXPECTED_SHA: ${{ github.sha }}
HEALTH_URL: https://oneclickpostfactory-agent.woeinvests.workers.dev/healthz
run: |
set -eu
health_body="$(curl --fail --silent --show-error --retry 5 --retry-delay 2 --retry-all-errors "$HEALTH_URL")"
HEALTH_BODY="$health_body" EXPECTED_SHA="$EXPECTED_SHA" node <<'NODE'
const body = JSON.parse(process.env.HEALTH_BODY || "{}");
const expectedSha = process.env.EXPECTED_SHA;
const rollout = body.rollout || {};
if (body.ok !== true || body.liveness !== "ok") throw new Error("Worker liveness check failed");
if (body.release?.gitSha !== expectedSha || body.release?.versionTag !== expectedSha) {
throw new Error("Deployed Worker does not match the requested Git SHA");
}
if (body.release?.schemaContract !== "publication-ledger-v1") {
throw new Error("Deployed Worker does not advertise publication-ledger-v1");
}
if (body.release?.schemaContracts?.workerClaims !== "worker-claims-v1") {
throw new Error("Deployed Worker does not advertise worker-claims-v1");
}
if (rollout.tenantScope !== "allowlisted" || rollout.canaryRequired !== true) {
throw new Error("Production canary allowlisting is not active");
}
if (!Number.isInteger(rollout.allowedTenantCount) || rollout.allowedTenantCount < 1 || rollout.allowedTenantCount > 3) {
throw new Error("Production canary tenant count is outside the 1-3 limit");
}
if (rollout.generationEnabled !== false || rollout.providerDispatchEnabled !== false) {
throw new Error("Production generation or provider dispatch is unexpectedly enabled");
}
console.log(JSON.stringify({
ok: true,
workerVersionId: body.release?.workerVersionId || null,
gitSha: body.release?.gitSha || null,
tenantScope: rollout.tenantScope,
allowedTenantCount: rollout.allowedTenantCount,
generationEnabled: rollout.generationEnabled,
providerDispatchEnabled: rollout.providerDispatchEnabled,
}));
NODE
18 changes: 11 additions & 7 deletions docs/reliability-repair-progress.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Reliability repair progress

This file records implementation status, not production deployment or provider readiness. The final exact-SHA CI receipts are recorded on the relevant pull requests. A passing component test is not live account evidence.
This file records implementation and rollout status. Exact-SHA CI receipts remain on the relevant pull requests and deployment runs. A passing component test is not live account evidence.

## Sequence 1: release identity and complete CI gate

Merged to upstream through PR #2. `npm run ci` gates typecheck, the complete normal regression suite and the compiled-runtime smoke check. Deployment invokes that same gate. Cloudflare version metadata and the Git SHA are exposed separately from provider readiness.

Hosted Threads and Instagram remain unavailable; Facebook remains paused; LinkedIn compatibility is unverified; X requires a tenant-owned connection. No production deployment is claimed here.
Hosted Threads and Instagram remain unavailable; Facebook remains paused; LinkedIn compatibility is unverified; X requires a tenant-owned connection. The bounded production canary receipt is recorded below.

## D03 containment and async runtime isolation

Expand All @@ -20,17 +20,17 @@ This addresses cross-execution process-global leakage. It is not a claim that ev

## D22: explicit platform activation

Present in this branch: only exact persisted boolean `true` enables a platform. Missing rows, fields, null and false fail closed. The schema-owner bootstrap also contains default-false settings and matching UI semantics. Existing legacy true values are not mass-rewritten because their original intent cannot be inferred safely.
Merged to upstream through PR #5: only exact persisted boolean `true` enables a platform. Missing rows, fields, null and false fail closed. The schema-owner bootstrap also contains default-false settings and matching UI semantics. Existing legacy true values are not mass-rewritten because their original intent cannot be inferred safely.

## D04/D05/D06: source and angle claims and safe transport

This branch is stacked on `codex/atomic-worker-claims`, head `984d0afa1fdfd696153fa8615615b1e2d42596e3`. That dependency introduces the typed worker-claims contract, database-owned source/angle leases and fencing, atomic generation finalisation, and explicit Supabase RPC retry semantics.
Merged into upstream through the dependency chain completed by PR #9. The worker-claims layer introduces the typed worker-claims contract, database-owned source/angle leases and fencing, atomic generation finalisation, and explicit Supabase RPC retry semantics.

Ordinary ambiguous mutations are single-attempt. Only reads and RPCs whose exact request identities are designed to be idempotent opt into retries. This does not claim that every agent job/enqueue path already has durable uniqueness or fencing.

## D07/D08/D09: connected publication execution

The hosted Worker consumer is now wired in `codex/publication-ledger-v1`, fork PR `AyobamiH/social-agents#4`, not merely a collection of unused helper modules.
The hosted Worker consumer is wired and merged to upstream through PR #9, not merely a collection of unused helper modules.

### Execution boundary

Expand Down Expand Up @@ -71,8 +71,12 @@ The cross-repository integration workflow belongs to the private schema-owner re

The one-time hash-guarded source-edit workflow and script were removed after committing the source delta. No write-enabled test/codemod workflow remains from this cutover.

## Production remains gated
## Production limited canary

Neither schema nor consumer is deployed by this branch. Before rollout: review the paired PRs, establish canonical schema ownership, apply to isolated staging first, verify the capability receipt, drain old publication dispatch owners, quarantine unresolved legacy publications, then test a bounded authorised cohort. Never run old and new executors as competing owners of the same queue row. Rollback must preserve ledger-owned unknown states and must not replay the legacy queue.
The schema-first rollout reached production on 9 September 2026 after the paired schema and Worker changes merged. Production migration head `20260907055000` preserves 148 queue rows while quarantining 11 members of five historical conflict groups behind immutable legacy revision holds. The persistent WSL staging rehearsal passed all 16 real Supabase/Postgres failure scenarios with provider transport intercepted and zero live posts.

Upstream PR #9 merged as `3a27a993742151a6558089c9ab0ade6b1a762ba4`. Guarded deployment run #79 then passed complete CI and deployed Cloudflare Worker version `773bb17d-59ef-484d-ae74-2f7c004e3447` with a one-tenant allowlist, batch size one, generation disabled and provider dispatch disabled. A post-deployment production snapshot at `2026-09-09T13:10:52Z` retained all 148 queue rows and 11 held revisions, with zero active jobs, publishing rows, generation rows, publication intents or publication attempts and zero jobs touched since deployment.

This is an inert, fail-closed production canary, not provider-readiness evidence. Production expansion remains gated on a separately reviewed configuration change, an authorised cohort and an observation receipt. Never run old and new executors as competing owners of the same queue row. Rollback must preserve ledger-owned unknown states and must not replay the legacy queue.

Remaining programme work includes connection lifecycle/version fences, billing inbox and entitlements, durable generation budgets, fair scheduling and typed UI recovery, provider restoration/compatibility, and account-authorised scheduled canaries. Do not describe the whole SaaS as production-repaired based on this publication slice alone.
11 changes: 8 additions & 3 deletions src/cloudflare-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ interface ExecutionContext {
waitUntil(promise: Promise<unknown>): void;
}

const SCHEMA_CONTRACT = 'pre-publication-ledger-v1';
const WORKER_SCHEMA_CONTRACT = 'worker-claims-v1';
const PUBLICATION_SCHEMA_CONTRACT = 'publication-ledger-v1';
const scheduledTickGate = createExclusiveRunGate();

function canonicalGitSha(versionTag: string | undefined): string | null {
Expand Down Expand Up @@ -121,8 +122,12 @@ function healthPayload(env: Env): Record<string, unknown> {
versionTag: metadata?.tag || null,
gitSha: canonicalGitSha(metadata?.tag),
versionTimestamp: metadata?.timestamp || null,
schemaContract: SCHEMA_CONTRACT,
appliedSchema: 'unverified',
schemaContract: PUBLICATION_SCHEMA_CONTRACT,
schemaContracts: {
workerClaims: WORKER_SCHEMA_CONTRACT,
publicationLedger: PUBLICATION_SCHEMA_CONTRACT,
},
appliedSchema: 'not_evaluated',
},
publicationCapabilities: publicationCapabilities(),
rollout: {
Expand Down
5 changes: 5 additions & 0 deletions test/canary-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ function main(): void {
);
assert.match(workflow, /SUPABASE_WORKER_CANARY_USER_IDS/);
assert.match(workflow, /--secrets-file/);
assert.match(workflow, /wrangler deploy --env=""/);
assert.match(workflow, /Verify the exact fail-closed canary release/);
assert.match(workflow, /oneclickpostfactory-agent\.woeinvests\.workers\.dev\/healthz/);
assert.match(workflow, /body\.release\?\.gitSha !== expectedSha/);
assert.match(workflow, /rollout\.providerDispatchEnabled !== false/);

console.log('Canary rollout policy tests passed.');
}
Expand Down
8 changes: 6 additions & 2 deletions test/cloudflare-health.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ async function main(): Promise<void> {
assert.equal(body.release.workerVersionId, 'worker-version-id');
assert.equal(body.release.versionTag, gitSha);
assert.equal(body.release.gitSha, gitSha);
assert.equal(body.release.schemaContract, 'pre-publication-ledger-v1');
assert.equal(body.release.appliedSchema, 'unverified');
assert.equal(body.release.schemaContract, 'publication-ledger-v1');
assert.deepEqual(body.release.schemaContracts, {
workerClaims: 'worker-claims-v1',
publicationLedger: 'publication-ledger-v1',
});
assert.equal(body.release.appliedSchema, 'not_evaluated');
});

await test('health does not advertise disabled or unverified publishers as ready', async () => {
Expand Down
Loading