From 6de5f18c64c81992bc23992adba839f6c5ac6f10 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Fri, 14 Aug 2026 08:14:48 +0100 Subject: [PATCH 1/3] docs(publisher-services): reconcile BE-03 post-merge state Implement BE-03-CLOSEOUT-01 against the exact CTO-authorized develop base b51bcc0905ac17fc0c142b2002b11fec711331a3. Correct the materially stale active Publisher Services programme and dependency state left after the BE-03 implementation merged. Active controls now record BE-03 as CLOSED - INACTIVE FOUNDATION and record the BE-03 dependency as satisfied for BE-04, MIG-01, APP-01 and APP-02 without any of them becoming ready: BE-04 remains BLOCKED and NOT STARTED with no durable job, target, attempt, automatic onboarding or dissemination in existence; MIG-01 remains CRITICAL and blocked by its audit, backfill and production prerequisites; APP-01's satisfied backend-contract dependency is scoped to its configuration-only surface while its app-readiness controls, exact-SHA contract pinning and own approved specification still gate it and its job-aware elements still require BE-04; APP-02 remains blocked on BE-04 and APP-01. Correct the BE-03 specification's own lifecycle-boundary prose only - its Status line, header implementation-authorization block and section 23 - with no change to any requirement, invariant, architecture, API contract, authorization matrix, migration decision, acceptance criterion, test obligation or BE-04 transaction seam. Record this task's own durable approval and implementation authorization. Documentation and control records only: no runtime, schema, migration, GraphQL, generated contract, client artifact, Cargo, workflow, deployment or environment change. Under ADR-0005 no review, approval or merge-authorization identifier, merge commit SHA or merge timestamp is transcribed; the self-resolving authority-condition construction of the BE-03/BE-04/APP-01 phase-boundary decision is preserved as written; and historical implementation-time evidence, including every migration-path reference later renamed by PR #811, is preserved unchanged. Deployment, environment and production migration execution, package commercial backfill, assignment creation/backfill, durable job creation, dissemination, distribution activation, OBSERVE/ENFORCE, workflow changes or dispatch and production access all remain NOT AUTHORIZED. Issues #765 and #766 and PR #799 are untouched. --- CHANGELOG.md | 1 + ...BE-03-CLOSEOUT-01-implementation-report.md | 804 ++++++++++++++++++ .../ai-delivery/tasks/BE-03-CLOSEOUT-01.md | 15 +- docs/engineering/ai-delivery/tasks/BE-03.md | 38 +- docs/publisher-services/README.md | 32 +- docs/publisher-services/decisions.md | 11 +- docs/publisher-services/rollout-plan.md | 32 +- docs/publisher-services/task-status.md | 77 +- 8 files changed, 935 insertions(+), 75 deletions(-) create mode 100644 docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b4bbb9a..0e8581e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added + - `BE-03-CLOSEOUT-01`: correct the materially stale active Publisher Services programme and dependency state left after the `BE-03` implementation merged. Active controls now record `BE-03` as `CLOSED - INACTIVE FOUNDATION`, and stop asserting that `BE-03` is unmerged, a draft, in review, awaiting independent review or merge authorization, `NOT AUTHORIZED`, or that `feature/publisher-services/be-03` must not exist. The `BE-03` dependency is recorded as satisfied for `BE-04`, `MIG-01`, `APP-01` and `APP-02` **without** any of them becoming ready: `BE-04` remains `BLOCKED` and `NOT STARTED` with no `distribution_job`, `distribution_job_target` or `distribution_job_attempt` relation, no automatic back-catalogue job creation and no dissemination in existence; `MIG-01` remains `CRITICAL` and blocked by its audit, backfill and production prerequisites; `APP-01`'s satisfied backend-contract dependency is scoped to its configuration-only surface while its app-readiness controls, exact-SHA contract pinning and own approved specification still gate it and its job-aware elements still require `BE-04`; and `APP-02` remains blocked on `BE-04` and `APP-01`. Corrects the `BE-03` specification's own lifecycle-boundary prose without altering any approved requirement, invariant, architecture, API contract, authorization matrix, migration decision, acceptance criterion or test obligation, and adds the bounded `BE-03-CLOSEOUT-01` implementation report. **Documentation and control records only: no runtime, schema, migration, API, generated contract, client artifact or workflow change.** Under `ADR-0005` no review, approval or merge-authorization identifier, merge commit SHA or merge timestamp is transcribed into repository files, GitHub remains the terminal lifecycle authority, the self-resolving authority-condition construction of the `BE-03`/`BE-04`/`APP-01` phase-boundary decision is preserved as written, and historical implementation-time evidence — including every migration-path reference recorded at an exact implementation head and later renamed by PR [811](https://github.com/thoth-pub/thoth/pull/811) — is preserved unchanged. Deployment, environment and production migration execution, package commercial backfill, assignment creation/backfill, durable job creation, dissemination, distribution activation, `OBSERVE`/`ENFORCE`, workflow changes or dispatch and production access all remain **NOT AUTHORIZED**, and PR [799](https://github.com/thoth-pub/thoth/pull/799), issue [765](https://github.com/thoth-pub/thoth/issues/765) and issue [766](https://github.com/thoth-pub/thoth/issues/766) are untouched - `BE-03-CLOSEOUT-01-SPEC`: propose the bounded post-merge control-correction specification for `BE-03-CLOSEOUT-01` (`docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md`). Records the classified stale-state analysis of the active Publisher Services and shared engineering-control surface after the `BE-03` merge, and specifies the correction that must follow: `BE-03` recorded as `CLOSED - INACTIVE FOUNDATION`; the `BE-03` dependency recorded as satisfied for `BE-04`, `MIG-01`, `APP-01` and `APP-02` **without** any of them becoming ready — `BE-04` remains unspecified and unauthorized with no durable job, target, attempt or automatic onboarding behaviour in existence, `MIG-01` remains `CRITICAL` and blocked by its production audit/backfill prerequisites, `APP-01`'s satisfied backend-contract dependency is scoped to its configuration-only surface while its app-readiness controls, exact-SHA contract pinning and own specification still gate it and its job-aware elements still require `BE-04`, and `APP-02` remains blocked on `BE-04` and `APP-01`. Classifies every statement as `ACTIVE STALE STATE - CORRECT`, `HISTORICAL RECORD - PRESERVE`, `CURRENT AND CORRECT - PRESERVE` or `OUT OF SCOPE - PRESERVE`, forbidding global find/replace. Under `ADR-0005`, forbids any commit that merely transcribes a review, approval or merge-authorization identifier, PR [809](https://github.com/thoth-pub/thoth/pull/809)'s merge SHA or its merge timestamp, and preserves historical implementation-time evidence — including every migration-path reference recorded at an exact implementation head, which the later PR [811](https://github.com/thoth-pub/thoth/pull/811) forward-integration renamed (`BE-02` `20260812_v1.7.0` -> `20260811_v1.7.0`; `BE-03` `20260813_v1.7.0` -> `20260812_v1.7.0`, content and relative apply order preserved). Preserves the `ADR-0005` authority-condition construction of the `BE-03`/`BE-04`/`APP-01` phase-boundary programme decision rather than replacing it with a literal status token, correcting only the references outside that self-resolving construction. **Specification and control records only - no runtime, Cargo, GraphQL, schema, migration, workflow or infrastructure change, no closeout correction performed, and no implementation branch created.** The `BE-03-CLOSEOUT-01` implementation remains **NOT AUTHORIZED** pending explicit CTO authorization against a freshly verified base; `BE-04`, `MIG-01`, `APP-01`, `APP-02`, deployment, environment and production migration execution, package commercial backfill, assignment creation/backfill, durable job creation, dissemination, distribution activation, `OBSERVE`/`ENFORCE`, workflow dispatch, production access and PR [799](https://github.com/thoth-pub/thoth/pull/799) all remain outside scope and unauthorized - `BE-03`: implement the approved bounded **protected publisher service configuration** as an inactive additive foundation. Adds the canonical optimistic-concurrency token `publisher.service_configuration_updated_at` (`timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL`, strictly increasing per publisher through `GREATEST(CURRENT_TIMESTAMP, previous + interval '1 microsecond')`), the closed two-value `publisher_service_configuration_source` type (`SUPERUSER_API`, `MIGRATION_BACKFILL`; no `OTHER`, no `UNKNOWN`, no `Default`) and the append-only `publisher_service_configuration_history` audit table (`actor text NOT NULL` with a named non-whitespace check constraint `CHECK (actor ~ '[^[:space:]]')`, enforcing that an audit actor contains at least one non-whitespace character, `ON DELETE CASCADE` foreign key, and a deterministic `(publisher_id, created_at DESC, id DESC)` composite index), with `thoth-api/src/schema.rs` updated manually and atomically in the same PR under `ADR-0003` Architecture A. Introduces **exactly one authoritative production write path** — the service-configuration write coordinator — which owns every committed write of package, enabled-platform desired state, configuration version token and audit history in one transaction on one connection under an explicit caller-supplied source/actor context, taking the publisher row lock first, rejecting a stale `expectedUpdatedAt` before any validation or lifecycle call, pre-validating the whole normalized desired platform set, applying platform state only through `BE-02`'s lifecycle primitives, committing the package and the token together in **exactly one** publisher `UPDATE` written directly (so no `publisher_history` row is written, and the shared `AFTER UPDATE` work-freshness cascade runs once per committed change whatever its shape, while a true no-op or stale request issues zero publisher `UPDATE`s), and writing exactly one audit row per committed change with bounded three-key canonical before/after state. Refactors `BE-02`'s lifecycle additively into connection-scoped `enable_on`/`disable_on` primitives that return a `#[must_use]` `Changed`/`Unchanged` outcome and validate `is_assignable()` themselves before any write, leaving the pool-level `enable`/`disable` signatures, semantics, early non-assignable check and existing tests unchanged and keeping exactly one linked-platform algorithm in the repository — so a membership-equal but split OAPEN/DOAB pair is **repaired**, bumping the token and writing one audit row, while a fully normalized request is a true no-op that writes nothing. Adds the protected `PublisherServiceConfiguration` type exposing the publisher, `subscriptionPackage`, `effectiveCapabilities`, `enabledDistributionPlatforms` and the version token; effective capabilities are **derived on read** from the canonical package through `BE-01`'s code-owned `ThothPackage::capabilities()` in that slice's order and persisted nowhere, so no package/capability inconsistency is representable and a package change updates them automatically. Adds the owner-and-superuser `publisherServiceConfiguration` query under a least-privilege per-publisher check (superuser, or exactly `PUBLISHER_USER` for that publisher's organisation, with **no role inheritance**: `PUBLISHER_ADMIN`, `WORK_LIFECYCLE` and `CDN_WRITE` without `PUBLISHER_USER` are denied, and a `NULL` `zitadel_id` fails closed for every non-superuser), the superuser-only `publisherServiceConfigurations` staff report and `publisherServiceConfigurationCount` with `[Uuid!] = []`, `[ThothPackage!] = []` and `[DistributionPlatform!] = []` filters, `AND` semantics for `enabledPlatforms`, a mandatory `publisher_id ASC` tie-breaker and a bounded two-statement page (one publisher page plus one `DISTINCT ON` latest-change lookup, with assignments resolved through `BE-02`'s existing request-local `ADR-0007` loader and **no second loader**), and the superuser-only `replacePublisherServiceConfiguration` mutation. Adds exactly one new error variant, `ThothError::StalePublisherServiceConfiguration`, and exactly one new `into_field_error` arm, `STALE_SERVICE_CONFIGURATION`, disclosing no SQL, column name or current token; every other error family keeps its merged mapping. `ThothPackage` and `PublisherCapability` become SDL-reachable for the first time, exclusively through the protected type: neither is on the public `Publisher`, and no package or capability value is anonymously readable. **Accepted and measured consequence:** because the token is a `publisher` column, every committed change — including a platform-only change and a linked-state repair — also moves `publisher.updated_at` and refreshes `work.updated_at_with_relations` for every work of that publisher through the existing `AFTER UPDATE` trigger's single set-based statement (never a per-work application loop), invalidating that publisher's cached export records; a stale request, a true no-op and a rolled-back transaction move none of the three values, and another publisher's works are never touched. **Inactive foundation only: the migration creates zero audit rows and changes no package or assignment; no distribution job, job target, job attempt or fabricated job status exists; no dissemination, upload or feed is produced; no capability state is persisted; no production migration, deployment, environment migration, backfill or distribution activation is performed; mutation-guard mode is unchanged; and no `BE-04`, `MIG-01`, `APP-01`, `APP-02` or PR [799](https://github.com/thoth-pub/thoth/pull/799) work is included.** - `BE-03-SPEC`: propose the complete bounded implementation specification for `BE-03` - **protected service configuration** (`docs/engineering/ai-delivery/tasks/BE-03.md`). Settles the full contract for the protected `PublisherServiceConfiguration` type — which, per `ADR-0001` section 4.4, exposes the current package, the **effective capability codes** and the enabled distribution platforms — the owner-and-superuser `publisherServiceConfiguration` query with its complete deny/allow matrix resolved through the existing ZITADEL publisher-role model (no new ownership table, no new role), the superuser-only paginated and deterministically ordered `publisherServiceConfigurations` staff report with publisher/package/enabled-platform filters declared in the merged repository shape (`[Uuid!] = []`, `[ThothPackage!] = []`, `[DistributionPlatform!] = []`), and the superuser-only `replacePublisherServiceConfiguration` mutation executing in exactly one transaction with a documented deterministic lock order matching `BE-02`. Effective capabilities are **derived on read** from the canonical `subscription_package` through `BE-01`'s code-owned `ThothPackage::capabilities()`, in that mapping's canonical order, and are **persisted nowhere** — no capability column, table, override or cache, no second mapping, and no capability input — so no package/capability inconsistency is representable and a package change updates them automatically; they are protected by the same single read decision as the rest of the type and must not appear on the public `Publisher`. States the protected read as a **least-privilege per-publisher check** — superuser, or exactly `PUBLISHER_USER` for the target publisher's organisation — with **no role inheritance**, so `PUBLISHER_ADMIN`, `WORK_LIFECYCLE` or `CDN_WRITE` without `PUBLISHER_USER` are denied and commercial package visibility is not widened by an unrelated scoped capability. Fixes one authoritative internal **service-configuration write coordinator** owning every committed write of package, enabled-platform desired state, canonical configuration version and configuration audit history in one caller-owned transaction under an explicit source/actor context, with `BE-02`'s pool-level `enable`/`disable` retained unchanged but reclassified as lower-level domain/compatibility functions barred from new production configuration call sites, and required call-site and bypass-search evidence. Selects a **dedicated `publisher.service_configuration_updated_at` concurrency token** with a strict per-publisher monotonicity rule, recording why `publisher.updated_at` and a computed multi-timestamp maximum were rejected, and documenting the accepted consequences that follow from the token being a `publisher` column: `public.publisher` carries **two** existing `UPDATE` triggers, so every committed configuration change — including a platform-only change or a linked-state repair — moves the public `Publisher.updatedAt` through `set_updated_at` **and** refreshes `work.updatedAtWithRelations` for every work of that publisher through its imprints through the existing `AFTER UPDATE` `set_work_updated_at_with_relations`, while a stale request, a true no-op and a rolled-back transaction move none of the three values and no other publisher's works are ever touched. The work-freshness value is a **public downstream signal** that invalidates that publisher's cached export records, so a platform-only change and a linked-state repair newly cause a cascade merged `BE-02` does not cause; the committed transaction therefore writes one publisher row plus bounded configuration/audit rows plus N related work rows through **one set-based trigger statement, never a per-work application loop**, with row-lock footprint and transaction duration growing with catalogue size while the publisher lock is held, and `BE-04` inherits this with the same transaction boundary. The token stays on `publisher` because a separate version table — whose genuine benefit for platform-only persistence is recorded honestly — would not avoid the same cascade for canonical package changes while `BE-01`'s `subscription_package` remains on `publisher`, and eliminating it fully would mean wider changes to approved `BE-01` storage or shared publisher trigger semantics; acceptance is therefore **evidence-conditional**, requiring six-case evidence against a real disposable PostgreSQL database with at least two imprints, at least two target works and a control work of another publisher, plus a catalogue-scale write-amplification and lock-footprint measurement recorded without production extrapolation, and a new stop condition requiring `BLOCKED` and a separate architecture escalation — never a silent trigger or storage change — if that evidence is bad. This freshness cascade is **not** distribution activation: no distribution job, upload, feed or dissemination is created. `Publisher.updatedAt` is explicitly **not** the configuration concurrency token, the protected values themselves stay behind the single read decision (timing correlation is acknowledged rather than denied), and the token's addition to the `Publisher` struct may surface as an additional key in future `publisher_history.data` snapshots; specifies the additive `publisher_service_configuration_history` audit table with an explicit `actor text NOT NULL` column (non-blank check constraint; following the repository's established account-FK-free actor representation but deliberately not named `user_id`, because `source` fixes the actor's provenance) and a closed two-value `source` type whose `SUPERUSER_API`/`MIGRATION_BACKFILL` actor contract is defined now, binding a future `MIG-01` to the same coordinator, the same token update and the same audit invariants while creating no job; plus bounded canonical before/after state that exposes no credential, endpoint, activation identifier or unrelated publisher metadata; requires reuse of `BE-02`'s linked OAPEN/DOAB normalization and non-assignable `JISC_NBK` behaviour through an additive connection-scoped refactor rather than a second implementation, with the primitives reporting whether they changed persisted state so that a **membership-equal but split OAPEN/DOAB pair is repaired rather than skipped** — a repair being a committed change that bumps the token and writes exactly one audit row — and with the connection-scoped enable primitive required to check `is_assignable()` **itself** before any write, as defence in depth alongside the retained pool-level early check and the coordinator's whole-set pre-validation; and requires reuse of `BE-02`'s existing request-local `ADR-0007` assignment DataLoader rather than a second equivalent loader. Raises one **programme-decision candidate** for CTO approval, under a durable `ADR-0005` authority condition rather than a mutable status word — it becomes an approved programme decision when the exact specification content carrying it receives explicit CTO specification approval **and** that content is reachable from `develop`, with no separate lifecycle-status commit required: `BE-03` owns desired configuration only and creates no `distribution_job`, `distribution_job_target` or `distribution_job_attempt` row, no placeholder job and no fabricated job status, with `BE-04` later extending the same transaction boundary; the decision additionally reconciles `APP-01`, whose configuration scope BE-03 satisfies but whose durable job, attempt, failure and pending-onboarding elements require `BE-04`. **Specification and control records only - no runtime, Cargo, GraphQL, schema, migration, workflow or infrastructure change, no implementation, and no implementation branch created.** `BE-03` implementation remains **NOT AUTHORIZED** and `feature/publisher-services/be-03` must not exist; `BE-04`, `MIG-01`, `APP-01`, `APP-02`, deployment, environment and production migration, assignment backfill, distribution activation, `OBSERVE`/`ENFORCE` and PR [799](https://github.com/thoth-pub/thoth/pull/799) all remain outside scope and unauthorized diff --git a/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md b/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md new file mode 100644 index 00000000..71d825c4 --- /dev/null +++ b/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md @@ -0,0 +1,804 @@ +# BE-03-CLOSEOUT-01 Implementation Report + +## 1. Repository state + +Repository: `thoth-pub/thoth` +Workflow: STANDARD +Base branch: `develop` +Base commit: `b51bcc0905ac17fc0c142b2002b11fec711331a3` +PR target: `develop` +Programme integration branch: None +Task branch: `feature/publisher-services/be-03-closeout` +Head commit: recorded in the pull request; this report is written at the branch +head that carries it +Pull request: draft pull request against `develop`; live state is the GitHub +pull-request record +Expected branch deletion after merge: YES +Final programme PR required: NO +Implementing model: Claude Opus 5 +Reasoning level: Extra High / xhigh + +### 1.1 Exact authorized base + +The CTO authorized implementation against exact `develop` head: + +```text +b51bcc0905ac17fc0c142b2002b11fec711331a3 +``` + +### 1.2 Preflight, performed before branch creation and before any edit + +```text +origin/develop = b51bcc0905ac17fc0c142b2002b11fec711331a3 MATCH +b51bcc09 parents = a4585a8d89166577da5ce6f46ce51ddb134b3f7e (first) + d952a83206ad846c7a01f70c29fe694bc8cd5561 (spec content) +b51bcc09 identity = merge commit of PR #812 +PR #812 = MERGED, base develop, + head feature/publisher-services/be-03-closeout-spec, + mergeCommit b51bcc09 +BE-03-CLOSEOUT-01.md at base = present; blob 2f23caf076ba963bc38b24d3c8b8f5a5e9261429, + byte-identical to the blob at d952a832 +PR #809 = MERGED, base develop, + mergeCommit 3ba4452c316399d80cd8d85e7d5e1bd05e252664 +PR #809 ancestry = 3ba4452c is an ancestor of b51bcc09 (verified with + git merge-base --is-ancestor) +BE-03 implementation at base = thoth-api/migrations/20260812_v1.7.0/{up,down}.sql present +Local branch feature/publisher-services/be-03-closeout = does not exist +Remote branch feature/publisher-services/be-03-closeout = does not exist +Open BE-03-CLOSEOUT-01 implementation PR = none + (open PRs: #799, #752, #744, #742, #668) +Committed competing closeout implementation record = none +Working tree = clean +``` + +`origin/develop` matched the authorized SHA exactly, so no intervening-commit +inspection was required. The pre-existing branch +`feature/publisher-services/be-03-closeout-spec` is the merged specification +branch, not a competing implementation branch. + +Repository instructions read before any edit: root +[`AGENTS.md`](../../../../AGENTS.md), +[`docs/engineering/AGENTS.md`](../../AGENTS.md), the approved specification +[`BE-03-CLOSEOUT-01`](../tasks/BE-03-CLOSEOUT-01.md) and +[ADR-0005](../../decisions/ADR-0005-terminal-merge-evidence.md). No more +specific `AGENTS.md` applies: the diff touches no workspace member and no +workflow directory. + +Branch creation: + +```bash +git switch -c feature/publisher-services/be-03-closeout b51bcc0905ac17fc0c142b2002b11fec711331a3 +``` + +## 2. Scope confirmation + +Approved specification: +[`BE-03-CLOSEOUT-01`](../tasks/BE-03-CLOSEOUT-01.md) + +Implemented objective: correct the materially incorrect active Publisher +Services programme and dependency state left behind after the BE-03 +implementation merged, so that active controls durably record BE-03 as +`CLOSED - INACTIVE FOUNDATION` and record each downstream dependency +accurately — satisfied where the merge satisfied it, and still blocked +everywhere else. + +Out-of-scope changes made: NONE. Every changed path is one of the paths the +specification lists in its section 3. No additional documentation path was +required. + +## 3. Commits + +- `docs(publisher-services): reconcile BE-03 post-merge state` - the single + bounded commit carrying this closeout. Its SHA is the branch head recorded in + the pull request. + +## 4. Files changed + +- `docs/publisher-services/task-status.md` + - reason: the active programme tracker recorded BE-03 as + `IMPLEMENTATION IN REVIEW` with a `(draft)` PR cell, an acceptance cell + reading `IMPLEMENTATION DELIVERED, NOT MERGED`, a `Last updated` note and + next-actions 10, 11 and 12 describing BE-03 as unmerged and awaiting fresh + review and CTO merge authorization, and listed BE-03 as an unsatisfied + blocking dependency of BE-04, MIG-01, APP-01 and APP-02. + - behavioural effect: none. BE-03 is now recorded as `CLOSED` with acceptance + `CLOSED - INACTIVE FOUNDATION`; BE-04, MIG-01, APP-01 and APP-02 record the + BE-03 dependency as satisfied while retaining every remaining blocker and + their `BLOCKED` / `NOT STARTED` status; the transient review-lifecycle + narrative is replaced by durable prose that points at the pull-request + record under ADR-0005. + +- `docs/publisher-services/README.md` + - reason: the header status line and the section 5 decision block asserted + `BE-03 IMPLEMENTATION NOT AUTHORIZED`; gating reason 1 repeated it; the + closing paragraph said an approved specification does not "unlock `BE-03`". + - behavioural effect: none. The decision block now records BE-03 as a closed + inactive foundation and states the downstream position for BE-04, MIG-01, + APP-01 and APP-02 explicitly, together with the expanded + `NOT AUTHORIZED` list. + +- `docs/publisher-services/rollout-plan.md` + - reason: the BE-02 implementation state block ended with "`BE-03` + implementation is `NOT AUTHORIZED`", and section 2.2 bound "the later + `BE-03`" in the future tense with a future-tense item 1. + - behavioural effect: none. A `BE-03 implementation state` block records the + merged inactive foundation on the same terms as the BE-02 block; section + 2.2 now binds APP-01 and states that the reserved control binds against + BE-03's reviewed implementation head. The control's substance is unchanged. + +- `docs/publisher-services/decisions.md` + - reason: the section 3a APP-01 reconciliation asserted in the present tense + that APP-01 "remains blocked on BE-03 exposing the approved protected + API", which the BE-03 merge falsified; the `Last updated` line needed to + reflect this change. + - behavioural effect: none. See section 5.2 for the explicit control ruling + and its application. The self-resolving ADR-0005 authority-condition + construction is preserved verbatim. + +- `docs/engineering/ai-delivery/tasks/BE-03.md` + - reason: the approved BE-03 specification carried `Status: DRAFT`, a header + implementation-authorization block reading "**separate and absent** ... The + branch `feature/publisher-services/be-03` must not exist", and a section 23 + lifecycle boundary asserting "BE-03 implementation status is + `NOT AUTHORIZED`". + - behavioural effect: none. Only the three lifecycle-boundary sites the + specification authorizes are changed. No requirement, invariant, + architecture, API contract, authorization matrix, migration decision, + acceptance criterion, test obligation, operational consequence or BE-04 + transaction seam is altered. + +- `docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md` + - reason: this task's own durable specification decision state was `DRAFT` + and its section 18 approval record was empty, both of which the + specification's CTO approval and merge through PR #812 falsified. + - behavioural effect: none. `Status: APPROVED`; section 18 records the + durable implementation authorization and the exact authorized base. The + header rule "Implementation authorization: **separate.**" is retained + unchanged as a durable rule. + +- `docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md` + - reason: required by the specification section 14 and root `AGENTS.md` + section 14. + - behavioural effect: none; new evidence record. + +- `CHANGELOG.md` + - reason: root `AGENTS.md` section 13 requires an entry under + `## [Unreleased]`. + - behavioural effect: none. One entry added as the first item under the + existing `### Added` heading. No heading was created or duplicated. + +## 5. Implementation decisions + +Decisions made within the approved design: + +1. **Durable rather than transient prose throughout.** Every corrected sentence + was re-read against the ADR-0005 section 6 test and stays truthful before + review, after review, before merge and after merge. No corrected sentence + says "awaiting review", "pending merge", "draft PR" or "merge authorization + outstanding" as current programme state. This closeout therefore does not + create the need for another closeout when it merges. +2. **No lifecycle metadata transcribed.** No independent review identifier, CTO + approval identifier, merge-authorization identifier, PR #809 merge commit + SHA or merge timestamp is written into any repository file. Where the + previous prose narrated the BE-03 review history (the earlier BLOCKED + exact-head review and the authorized bounded remediation), that narrative + was removed from the active tracker rather than updated, because ADR-0005 + section 5 makes the GitHub pull-request record the authority for it. Pointers + to PR #808 and PR #809 are retained; they are references, not transcriptions. +3. **`BE-03.md` corrections confined to the three authorized sites.** The + `Status` line uses the house form established by `ADR-01.md` + (`APPROVED AND REPOSITORY-AUTHORITATIVE - ...`) rather than a bare + `APPROVED`, so the line records both the specification's durable decision + state and the inactive-foundation delivery boundary in one place. +4. **`rollout-plan.md` gains a `BE-03 implementation state` block** modelled on + the existing BE-02 block rather than an inline clause, so the inactive + foundation and the satisfied-but-not-ready downstream position are stated + once, coherently, in the document that owns rollout state. The block is + deliberately undated: BE-03's merge date is transient GitHub evidence. +5. **`README.md` decision block expanded per downstream task.** The block + previously carried a single BE-03 line. It now states BE-04, MIG-01, APP-01 + and APP-02 positions explicitly, because a bare "BE-03 CLOSED" would leave a + reader to infer the downstream consequence, which is exactly the inference + the specification forbids. +6. **Two `Last updated` metadata lines refreshed** (`task-status.md` line 7 and + `decisions.md` line 4). Both were accurate at the authorized base and became + inaccurate as a direct consequence of this change; refreshing them follows + the BE-02-CLOSEOUT-01 precedent. + +Deviations from the specification: NONE. + +Scope deviations on touched paths: NONE. The changed set is exactly the +specification's expected set. `platform-inventory.md`, `acceptance-matrix.md`, +`master-issue.md` and `control-gaps.md` were searched and left untouched, as +expected. + +### 5.1 Two fresh findings not present in the authoring-time Annex A + +Both fall inside an already-expected touched path and inside the approved +scope; neither required a new path. + +1. `task-status.md` next-action 6: "BE-03 later exposes the protected + package/capability contract under its own approval gates" — a future-tense + BE-03 lifecycle assertion about something that has now happened. Classified + `ACTIVE STALE STATE - CORRECT` and corrected to the past tense, retaining the + "under its own approval gates" qualifier and adding "as a merged but equally + inactive foundation". +2. `task-status.md` next-action 9: "BE-03 later exposes the protected service + configuration under its own approval gates" — same class, same correction. + +Annex A did not record either, which is why the specification requires the +search to be repeated rather than applied from the annex. + +### 5.2 `decisions.md` section 3a - classification and CTO control ruling + +The authoring-time Annex A classifies `decisions.md` section 3a +`CURRENT AND CORRECT - PRESERVE` "in its entirety", while the normative +specification section 2 and its `ACTIVE STALE STATE` list identify one +present-tense sentence inside the same section as stale. The CTO resolved this +wording collision explicitly, and the normative sections control over the +informative annex. + +**Ruling applied.** The self-resolving ADR-0005 authority-condition +construction is preserved as written, including: + +- `Decision state: PROPOSED IN THIS SPECIFICATION CANDIDATE` (line 247, + unchanged); +- the two-part authority condition (lines 251-256, unchanged); +- the rule that once both parts hold it is an `APPROVED PROGRAMME DECISION` + "without requiring a separate lifecycle-status edit to this file" (lines + 258-261, unchanged); +- the explanation of why a literal mutable `APPROVED` token is not required + (lines 263-269, unchanged); +- the deliberate "This decision candidate **refines and, in that narrow + respect, supersedes**..." phrasing that belongs to that construction (line + 336, unchanged). + +`PROPOSED` was **not** mechanically replaced with `APPROVED`, and no +architecture was rewritten. + +**Corrected.** One sentence only, in the APP-01 reconciliation: + +```text +before: ... and remains blocked on BE-03 exposing the approved protected API, + app readiness controls, the exact-SHA schema pinning control and its + own approved bounded specification. + +after: ... Its dependency on BE-03 exposing the approved protected API is + satisfied for the configuration-only surface enumerated below, BE-03 + having merged that surface; APP-01 itself remains blocked on app + readiness controls, the exact-SHA schema pinning control and its own + approved bounded specification, and its job-aware elements remain + dependent on BE-04 as set out below. +``` + +Classification: `ACTIVE STALE STATE - CORRECT`. + +Applying the ruling required **no** change to the BE-03/BE-04/APP-01 +architecture. The enumerated configuration-only scope (items 1-6 immediately +below the corrected sentence), the four BE-04-dependent elements, the APP-02 +dependency on both BE-03 and BE-04, and the consequences list are all unchanged +and continue to say exactly what they said. The stop condition "if applying this +ruling would require changing the BE-03/BE-04/APP-01 architecture, STOP BLOCKED" +therefore did not fire. + +## 6. Database and migration effects + +Migration added: NO + +No migration, schema, catalog or data change of any kind. +`thoth-api/src/schema.rs` and `thoth-api/migrations/` are untouched, as proved +by the negative path check in section 9. + +## 7. API and compatibility effects + +GraphQL/API changes: none. +Generated schema/client updates: none; `thoth-client/assets/schema.graphql` is +byte-identical to the base. +Backwards compatibility: unaffected. +Deprecations: none. +Cross-repository dependencies: none created. The reserved BE-03/APP-01 exact-SHA +schema-pinning control continues to bind against BE-03's reviewed implementation +head, not against this task's head; section 2.2 of `rollout-plan.md` now says so +explicitly. This task produces no new contract for a downstream repository to +pin. + +## 8. Authorization and security + +Authorization paths changed: none. +Roles/scopes involved: none. `thoth-api/src/policy.rs` and every authorization +test are untouched. +Negative authorization tests: not applicable; no authorization code is in this +diff. +Secret or personal-data handling: none. No credential, token, endpoint, bucket +or account identity is introduced into the diff. +Security limitations: none introduced. + +## 9. Tests and checks + +Root `AGENTS.md` section 8 prescribes the documentation-only evidence set and +reserves the full workspace gate for Rust/domain changes. No file under any +workspace member is modified, so the workspace gate has no changed input and was +not run. + +### Formatting + +Command: + +```text +git diff --check +``` + +Result: + +```text +no output; no whitespace error +``` + +### Path containment + +Command: + +```text +git diff --name-only b51bcc0905ac17fc0c142b2002b11fec711331a3..HEAD +``` + +Result: + +```text +CHANGELOG.md +docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md +docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md +docs/engineering/ai-delivery/tasks/BE-03.md +docs/publisher-services/README.md +docs/publisher-services/decisions.md +docs/publisher-services/rollout-plan.md +docs/publisher-services/task-status.md +``` + +Every path matches `^docs/` or is exactly `CHANGELOG.md`. + +### Negative runtime-path proof + +Command: + +```text +git diff --name-only b51bcc0905ac17fc0c142b2002b11fec711331a3..HEAD \ + | grep -E '^(thoth-api|thoth-api-server|thoth-client|thoth-errors|thoth-export-server|\.github|Cargo\.)' +``` + +Result: + +```text +no output +``` + +No runtime, migration, schema, GraphQL, generated client, workflow or Cargo file +changed. + +### Unit tests + +Not applicable: documentation-only change, no workspace member modified. + +### Integration/database tests + +Not applicable: no migration, schema or database-backed code is touched. + +### Lint/static analysis + +Not applicable to the changed paths. + +### Documentation link verification + +Command: + +```text +resolve every relative markdown link target in the changed files against the +filesystem +``` + +Result: + +```text +relative links checked: 92 +broken: 0 +``` + +## 10. Manual verification + +Environment: local checkout of `feature/publisher-services/be-03-closeout` at +the branch head, created from `b51bcc0905ac17fc0c142b2002b11fec711331a3`. + +Steps: the classified search was performed from the authorized base with +`git grep -n 'BE-03' -- docs/ CHANGELOG.md` (27 files), every hit was read in +context, and the search was re-run after the edits. + +### 10.1 Complete fresh classified stale-state findings + +#### `ACTIVE STALE STATE - CORRECT` + +- `docs/publisher-services/task-status.md` line 7 — `Last updated` note + describing BE-03 as delivered as a draft pull request with the new exact head + "awaiting a fresh independent review". Corrected. +- `docs/publisher-services/task-status.md` BE-03 row — status + `IMPLEMENTATION IN REVIEW`; blocking-dependency cell listing a fresh + independent review and CTO merge authorization as remaining gates; PR cell + `(draft)`; acceptance cell `IMPLEMENTATION DELIVERED, NOT MERGED`. Corrected + to `CLOSED` / `CLOSED - INACTIVE FOUNDATION`. +- `docs/publisher-services/task-status.md` BE-04 row — BE-03 listed as an + unsatisfied blocking dependency. Corrected to satisfied, with BE-04 retained + as `BLOCKED` / `NOT STARTED` and the explicit statement that no + `distribution_job`, `distribution_job_target`, `distribution_job_attempt`, + automatic back-catalogue job creation or dissemination exists. +- `docs/publisher-services/task-status.md` MIG-01 row — same, corrected to + satisfied with MIG-01 retained as `CRITICAL` / `BLOCKED` and its audit, + backfill, dry-run and CG-13 prerequisites retained. +- `docs/publisher-services/task-status.md` APP-01 row — BE-03 listed as an + unsatisfied blocking dependency, and "the candidate phase boundary". + Corrected: the backend-contract dependency is satisfied for the + configuration-only scope, APP-01 remains `BLOCKED` by its other controls, the + job-aware elements remain BE-04-dependent, and the boundary is referred to as + approved. +- `docs/publisher-services/task-status.md` APP-02 row — BE-03 listed as an + unsatisfied blocking dependency. Corrected to satisfied-only, with APP-02 + retained as blocked on BE-04 and APP-01 and an explicit statement that this + does not make it ready. +- `docs/publisher-services/task-status.md` next-action 6 — future-tense "BE-03 + later exposes the protected package/capability contract". Fresh finding, not + in Annex A; corrected. +- `docs/publisher-services/task-status.md` next-action 9 — future-tense "BE-03 + later exposes the protected service configuration". Fresh finding, not in + Annex A; corrected. +- `docs/publisher-services/task-status.md` next-action 10 — "delivered ... as a + **draft** pull request", the exact-head review narrative, "BE-03 is **not + merged**", the fresh-review requirement, "explicit CTO merge authorization + remains outstanding", and "programme-decision candidate". Corrected to durable + prose. +- `docs/publisher-services/task-status.md` next-action 11 — "APP-01 remains + blocked pending BE-03" and "the candidate phase boundary". Corrected. +- `docs/publisher-services/task-status.md` next-action 12 — "the separately + authorized, delivered-but-unmerged BE-03 implementation". Corrected, and the + unauthorized-action list extended to name package commercial backfill, durable + job creation, dissemination and workflow change/dispatch explicitly. +- `docs/publisher-services/README.md` line 3 header status — did not record + BE-03. Corrected. +- `docs/publisher-services/README.md` section 5 decision block — `BE-03 + DEPENDENCIES ON BE-01 AND BE-02 SATISFIED; BE-03 IMPLEMENTATION NOT + AUTHORIZED`. Corrected, and the per-downstream position added. +- `docs/publisher-services/README.md` gating reason 1 — "`BE-03` implementation + remains `NOT AUTHORIZED` pending its own approved bounded specification and + separate explicit authorization". Corrected. +- `docs/publisher-services/README.md` closing paragraph — an approved + specification does not "unlock `BE-03`". Corrected by removing `BE-03` from + the list only. +- `docs/publisher-services/rollout-plan.md` BE-02 implementation state block — + "`BE-03` implementation is `NOT AUTHORIZED`". Corrected, and a `BE-03 + implementation state` block added. +- `docs/publisher-services/rollout-plan.md` section 2.2 — "It binds the later + `BE-03` and `APP-01` tasks" and item 1's future-tense "`BE-03` produces an + exact generated GraphQL SDL at its reviewed head". Corrected without changing + the control's substance. +- `docs/publisher-services/decisions.md` section 3a APP-01 reconciliation — the + present-tense APP-01 dependency assertion. Corrected under the CTO control + ruling; see section 5.2. +- `docs/engineering/ai-delivery/tasks/BE-03.md` line 3 — `Status: DRAFT`. + Corrected. +- `docs/engineering/ai-delivery/tasks/BE-03.md` header + implementation-authorization block — "**separate and absent** ... must not + exist until the CTO separately and explicitly authorizes implementation". + Corrected. +- `docs/engineering/ai-delivery/tasks/BE-03.md` section 23 — "BE-03 + implementation status is `NOT AUTHORIZED`. The branch + `feature/publisher-services/be-03` must not exist...". Corrected. +- `docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md` line 3 — + `Status: DRAFT`, falsified by this specification's own CTO approval and merge + through PR #812. Corrected to `APPROVED`. +- `docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md` section 18 — empty + approval record. Completed with the durable implementation authorization. + +#### `HISTORICAL RECORD - PRESERVE` + +- `docs/engineering/ai-delivery/implementation-reports/BE-03-implementation-report.md` + in its entirety (30 BE-03 references), including its base and head commits, + exact test commands, CI record and every reference to + `thoth-api/migrations/20260813_v1.7.0` and to `20260812_v1.7.0` as BE-02's + migration. Untouched. +- `docs/engineering/ai-delivery/implementation-reports/BE-03-SPEC-implementation-report.md` + (111 references) — untouched. +- `docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-SPEC-implementation-report.md` + (43 references) — the specification task's own exact-head record. Untouched. +- `docs/engineering/ai-delivery/implementation-reports/BE-02-implementation-report.md`, + `BE-02-CLOSEOUT-01-implementation-report.md`, `BE-02-SPEC-implementation-report.md`, + `BE-01-implementation-report.md`, `BE-01-SPEC-implementation-report.md`, + `ADR-01-SPEC-implementation-report.md`, + `ADR-0002-APPROVE-implementation-report.md`, + `P0-01-CLOSEOUT-implementation-report.md`, + `P0-01-FINALIZE-implementation-report.md` — untouched. +- `docs/engineering/ai-delivery/tasks/BE-02-CLOSEOUT-01.md` lines 32, 74, 100 + and 252 — the completed BE-02 closeout's own scope, non-goals and merge-order + record, correct as written for that task. Untouched. +- `docs/engineering/ai-delivery/tasks/ADR-01-CLOSEOUT-01.md` line 183 — that + task's non-goal. Untouched. +- `docs/publisher-services/adr-01-evidence-matrix.md` line 256 — "future + BE-02/BE-03 implementation; not yet implemented at the inspected commits", an + ADR-01 evidence record explicitly bound to the commits it inspected. + Untouched. +- `CHANGELOG.md`'s existing `BE-03` entry from PR #809, `BE-03-SPEC` entry from + PR #808 and `BE-03-CLOSEOUT-01-SPEC` entry from PR #812 — append-only records + of what each pull request contained when written, including the + `BE-03-SPEC` entry's closing "`BE-03` implementation remains **NOT + AUTHORIZED** and `feature/publisher-services/be-03` must not exist". Preserved, + on the same basis BE-02-CLOSEOUT-01 used for the equivalent PR #805 entry. +- `docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md` sections 1, 2, 3, 9, + 10 and Annex A — this specification's own approved record of the pre-correction + state it exists to correct, including every quotation of the stale wording. + These are the approved specification's own content and its acceptance + criteria; rewriting them would rewrite the approved specification and + invalidate its own tests. Only `Status` and section 18 were changed. + +#### `CURRENT AND CORRECT - PRESERVE` + +- `docs/publisher-services/decisions.md` section 3a authority-condition + construction — `Decision state:` line, the two-part condition, the + self-resolution rule, the rationale against a mutable `APPROVED` token, and + the "decision candidate" phrasing belonging to it. Preserved verbatim; see + section 5.2. +- `docs/publisher-services/decisions.md` section 3a tension, proposed + resolution, transaction-boundary note, configuration-only scope list, + BE-04-dependent list, consequences and boundary-of-decision paragraphs — the + architecture itself. Untouched. +- `docs/publisher-services/decisions.md` operational invariants 3 and 7 — + backfill creates no back-catalogue jobs; automatic job creation is initially + inactive. Untouched. +- `docs/publisher-services/README.md` section 5 item 6 — protected package and + effective-capability reads and the dedicated superuser package mutation + remain BE-03 scope. Untouched. +- `docs/publisher-services/rollout-plan.md` dependency graph and the structural + statement "`BE-03` depends on both `BE-01` and `BE-02`". Untouched. +- `docs/publisher-services/rollout-plan.md` control "`thoth-app` must not begin + `APP-01` implementation until `BE-03` exposes the approved protected API" — a + durable rule whose condition is now satisfied; its wording stays truthful. + Untouched. +- `docs/publisher-services/rollout-plan.md` Stage 1-5 deliverables, controls, + exit evidence and rollback — rules and plan, not status claims. Untouched. +- `docs/publisher-services/adr-01-evidence-matrix.md` line 192 — the unpinned + `codegen.ts` observation confirming the reserved BE-03/APP-01 contract + control's concern; still true. Untouched. +- `docs/publisher-services/platform-inventory.md` — jobs are BE-04 scope and + automatic job creation is inactive; no BE-03 reference at this base. + Untouched. +- `docs/engineering/repository-map/control-gaps.md` CG-13 activation block, + including `BE-02 runtime: NOT AUTHORIZED`; CG-13 remains `OPEN`. No BE-03 + reference at this base. Untouched. +- `docs/engineering/ai-delivery/tasks/BE-03.md` section 24 approval boundary — + a statement about what specification approval does not authorize, still true. + Untouched. +- `docs/engineering/decisions/ADR-0001-publisher-package-capability-model.md` + line 334 — an architectural affected-task reference, not a lifecycle claim. + Untouched. + +#### `OUT OF SCOPE - PRESERVE` + +- `docs/publisher-services/acceptance-matrix.md` lines 14-20 — maps requirements + to owning tasks, evidence and activation gate; carries no BE-03 lifecycle + status claim. Untouched, as the specification expected. +- `docs/publisher-services/master-issue.md` — no BE-03 statement. Untouched. +- `docs/engineering/ai-delivery/tasks/BE-01.md` (9 references), + `BE-02.md` (5), `ADR-01.md` (11) — other tasks' approved specifications. Their + BE-03 references are structural task-decomposition and scope-boundary + statements ("BE-03 later owns the protected mutation", "`BE-03` depends on + both `BE-01` and `BE-02`", "the dedicated protected read and superuser + mutation belong to BE-03") rather than BE-03 lifecycle status claims. + Amending another task's approved specification is outside this task's scope + and is forbidden by its non-goal 9. Untouched. +- `docs/engineering/ai-delivery/tasks/THOTH-GQL-BATCH-01.md` line 1636 — the + acceptance criterion asserting that `BE-02` remains unimplemented with no + `DistributionPlatform` enum. A different programme's `DRAFT`, + `NOT AUTHORIZED` specification, and a scope-containment test on that task's + own future diff. Its premise is outdated; correcting it belongs to that task + and programme. Untouched, per the explicit instruction not to repair it here. +- `docs/publisher-services/README.md` section 5 item 7 — "no + `DistributionPlatform` enum exists in code". Materially false, but a BE-02 + assertion, not a BE-03 one. See section 13. Untouched. +- issue [#765](https://github.com/thoth-pub/thoth/issues/765), issue + [#766](https://github.com/thoth-pub/thoth/issues/766) and PR + [#799](https://github.com/thoth-pub/thoth/pull/799) — explicitly untouched. + +### 10.2 Migration-path classification + +Current repository migration names after PR #811, used by any new prose in this +change: + +```text +BE-02 current: thoth-api/migrations/20260811_v1.7.0/ +BE-03 current: thoth-api/migrations/20260812_v1.7.0/ +v1.6.3 chapter hotfix: thoth-api/migrations/20260813_v1.6.3/ +``` + +Historical implementation-head names, preserved wherever they appear: + +```text +BE-02 implementation head: 20260812_v1.7.0 +BE-03 implementation head: 20260813_v1.7.0 +``` + +Classification: every old-path reference in this repository lives in the BE-02, +BE-02-CLOSEOUT-01, BE-03, BE-03-SPEC and BE-03-CLOSEOUT-01-SPEC implementation +reports. Each is `HISTORICAL RECORD - PRESERVE`: correct at the exact head it +describes. None was rewritten. The BE-03 implementation report's rollout note +"Migration sequence: `20260813_v1.7.0` applies after `20260812_v1.7.0`" is +preserved: it was true as written and the ordering it asserts still holds under +the renamed directories. + +**Active path-related control debt: none found.** No active Publisher Services +or shared engineering-control document makes a present-tense operational +assertion about the BE-03 migration path. The finding matches Annex A's. No +migration was renamed or modified, no migration ordering was changed, and PR +#811 was not reviewed, reverted or repaired. + +This closeout's own new prose does not name a migration directory at all, so the +"use `thoth-api/migrations/20260812_v1.7.0/`" rule had no occasion to apply +outside this report. + +### 10.3 Historical implementation reports untouched + +Confirmed by the path containment result in section 9: no path under +`docs/engineering/ai-delivery/implementation-reports/` appears in the diff other +than this new report. The BE-02, BE-02-CLOSEOUT-01, BE-03, BE-03-SPEC and +BE-03-CLOSEOUT-01-SPEC implementation reports and all of their migration-path +references are byte-identical to the base. + +### 10.4 Post-edit classified re-run + +Command: + +```text +git grep -n 'BE-03' -- docs/ CHANGELOG.md +git grep -n -iE 'BE-03[^.]{0,80}(not merged|unmerged|NOT AUTHORIZED|awaiting|in review|must not exist|draft)' \ + -- docs/publisher-services/ docs/engineering/ai-delivery/tasks/ docs/engineering/repository-map/ docs/engineering/decisions/ +``` + +Result: every surviving hit of the stale-language pattern is inside +`docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md`, in that +specification's own background, scope, acceptance criteria, manual-verification +commands and Annex A — that is, its approved record of the state it exists to +correct. No hit remains in `task-status.md`, `README.md`, `rollout-plan.md`, +`decisions.md`, `BE-03.md`, `control-gaps.md` or any other active control +document. + +Observed result against each required assertion: + +- no active control says BE-03 is unmerged — confirmed; +- no active control says the BE-03 implementation is awaiting authorization, + review or merge — confirmed; +- no active control says BE-03 is an unsatisfied dependency where the merge + satisfied it — confirmed; +- BE-04 remains `BLOCKED` / `NOT STARTED`, unspecified and unauthorized, with no + durable job, target, attempt, automatic onboarding or dissemination + represented as existing — confirmed + (`git grep -n 'BE-04\|distribution_job' -- docs/publisher-services/`); +- MIG-01 remains `CRITICAL` / `BLOCKED` with its audit, backfill, dry-run and + CG-13 prerequisites — confirmed; +- APP-01 remains `BLOCKED` by BR-APP-01 or an explicit CTO exception, the CG-11 + CI closure work, exact-SHA contract pinning and its own approved + specification — confirmed; +- APP-01 job-aware state remains BE-04-dependent — confirmed in `task-status.md`, + `README.md` and `decisions.md`; +- APP-02 remains blocked on BE-04 and APP-01 and is not represented as ready — + confirmed; +- production, environment, migration-execution, backfill, job-creation, + dissemination, activation, `OBSERVE`/`ENFORCE`, workflow and production-access + actions remain `NOT AUTHORIZED` — confirmed + (`git grep -n 'NOT AUTHORIZED' -- docs/publisher-services/ docs/engineering/repository-map/control-gaps.md`); +- `decisions.md` authority-condition construction intact — confirmed by + inspecting the two-hunk diff for that file; +- historical implementation reports and their migration paths untouched — + confirmed; +- PR #799 untouched and not represented as a Publisher Services dependency — + confirmed (`git grep -n '799' -- docs/`: every hit is a pre-existing non-goal + or exclusion statement, none changed by this diff). + +### 10.5 Durability re-read + +Each corrected paragraph was re-read against the ADR-0005 section 6 test. No +corrected sentence depends on this pull request's own review, authorization or +merge state, so merging this closeout does not falsify any sentence it writes +and does not create the need for a further closeout. + +### 10.6 Changelog + +One entry added as the first item under the existing `## [Unreleased]` / +`### Added` headings. Verified: exactly one `## [Unreleased]` heading and +exactly one `### Added` heading in that section; no heading created or +duplicated. + +Evidence link: the pull-request diff and check record. + +## 11. CI + +CI status: PENDING at the time of writing. GitHub is the live authority; the +result is the pull request's check record. The change is expected to classify as +documentation-only. Actual results will be reported rather than assumed. + +## 12. Rollout and rollback + +Initial state after merge: repository documentation only; no runtime, +deployment, migration, backfill, activation or production effect. +Activation required: none; this task activates nothing. +Feature flag/configuration: none. +Migration sequence: not applicable; no migration is added, renamed or modified. +Rollback/disable procedure: ordinary revert of the documentation pull request +under normal review. +Monitoring required: none. + +## 13. Known limitations and deferred work + +- **Residual BE-02 control debt, deliberately not fixed here.** + `docs/publisher-services/README.md` section 5 item 7 states "It is a decision + record, not an implemented enum; no `DistributionPlatform` enum exists in + code." This is materially false — BE-02 merged the 17-value enum through PR + #805 — but it is a BE-02 assertion, not a BE-03 one. BE-02-CLOSEOUT-01's + acceptance criterion targeted exactly this class of statement and corrected + the `platform-inventory.md` and `control-gaps.md` instances; this README + instance survived. Recorded as deferred control debt for its own bounded task. + Recommended owner: CTO, as a bounded BE-02 residual-debt correction. +- **Different-programme stale premise, deliberately not fixed here.** + `docs/engineering/ai-delivery/tasks/THOTH-GQL-BATCH-01.md` line 1636 carries an + acceptance criterion premised on BE-02 being unimplemented. It belongs to a + different programme's `DRAFT`, `NOT AUTHORIZED` specification. Recommended + owner: that task and programme. +- **Adjacent observation, not actioned.** PR #811 placed the v1.6.3 hotfix + migration at `thoth-api/migrations/20260813_v1.6.3/`, which sorts after the + v1.7.0 publisher-services migrations at `20260811_v1.7.0` and + `20260812_v1.7.0`. That is PR #811's business, is out of scope here, and does + not affect the BE-02-then-BE-03 apply order. Recorded for the CTO only. +- **`BE-02.md` header.** The BE-02 specification header still reads + "Implementation authorization: separate and absent" although BE-02 has merged. + It is a BE-02 record, outside this task's scope, and is noted only so the + observation is not lost. + +## 14. Unresolved issues + +NONE. + +No repository authority conflict was found about what BE-03's merge satisfies. +The one wording collision inside the approved specification — Annex A's +"section 3a in its entirety" versus the normative sections' identification of +the APP-01 dependency sentence as stale — was resolved by explicit CTO control +ruling and is recorded in full in section 5.2. + +## 15. Agent self-assessment + +This agent implemented the change and does not approve it. The pull request +remains draft pending fresh independent exact-head review and separate CTO merge +authorization. + +Confirmations: + +- no runtime, schema, migration, GraphQL, generated-contract, client-artifact, + Cargo, workflow, deployment or environment change occurred (section 9 negative + path proof); +- issues #765 and #766 and PR #799 were untouched; no GitHub issue or pull + request other than this task's own draft PR was created or modified; +- BE-04, MIG-01, APP-01 and APP-02 were not started, specified or authorized, + and each retains its recorded blockers; +- no production or environment action occurred: no deployment, no migration + execution, no backfill, no assignment or job creation, no dissemination, no + activation, no `OBSERVE`/`ENFORCE` transition, no workflow dispatch and no + production access or credential use; +- no review, approval or merge-authorization identifier, merge commit SHA or + merge timestamp was newly transcribed into any repository file. + +Suggested review focus: + +1. **The `decisions.md` section 3a ruling application** (section 5.2). Confirm + the self-resolving authority-condition construction is intact and that the + single corrected sentence changes dependency state only, not architecture. +2. **Durability of every corrected sentence.** Confirm no sentence written here + becomes false when this pull request merges. +3. **The two fresh findings in section 5.1** that Annex A did not record, and + whether the classified search missed any comparable future-tense assertion. +4. **Downstream containment.** Confirm that satisfying the BE-03 dependency did + not make BE-04, MIG-01, APP-01 or APP-02 read as ready anywhere. +5. **`BE-03.md` blast radius.** Confirm only the three authorized + lifecycle-boundary sites changed and that no requirement, invariant, + acceptance criterion, test obligation or BE-04 transaction seam moved. diff --git a/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md b/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md index 2f23caf0..cd279b0b 100644 --- a/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md +++ b/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md @@ -1,6 +1,6 @@ # BE-03-CLOSEOUT-01 - Post-merge control correction for BE-03 -Status: DRAFT +Status: APPROVED Programme: Publisher Services and Distribution Configuration Repository: `thoth-pub/thoth` Workflow: STANDARD @@ -588,9 +588,16 @@ correction of materially stale active BE-03 programme state. ## 18. Approval -Approved for implementation by: -Date: -Notes: +Approved for implementation by: Javi, CTO +Date: 2026-08-14 +Notes: implementation was explicitly authorized against exact `develop` base +`b51bcc0905ac17fc0c142b2002b11fec711331a3`, the merge commit of this +specification's own pull request +[#812](https://github.com/thoth-pub/thoth/pull/812). Authorization is limited to +the documentation and control correction specified here — correcting materially +stale active BE-03 programme state. It authorizes no runtime, schema, migration, +GraphQL, generated contract, workflow, deployment, environment or production +action, and it starts, specifies or authorizes no other task. Record only the durable implementation authorization here. Independent review decisions, CTO merge authorization and the merge itself are terminal GitHub diff --git a/docs/engineering/ai-delivery/tasks/BE-03.md b/docs/engineering/ai-delivery/tasks/BE-03.md index 25f9f491..8eb6cae4 100644 --- a/docs/engineering/ai-delivery/tasks/BE-03.md +++ b/docs/engineering/ai-delivery/tasks/BE-03.md @@ -1,6 +1,7 @@ # BE-03 - Protected service configuration -Status: DRAFT +Status: APPROVED AND REPOSITORY-AUTHORITATIVE - BE-03 IMPLEMENTATION DELIVERED +AS AN INACTIVE FOUNDATION Programme: Publisher Services and Distribution Configuration Repository: `thoth-pub/thoth` Workflow: STANDARD @@ -27,11 +28,11 @@ content is reachable from the repository's authoritative integration branch (`develop`). Live review, authorization and merge evidence is the GitHub pull-request record and is not copied here. -Implementation authorization: **separate and absent.** This document specifies -BE-03; it does not authorize it. The branch `feature/publisher-services/be-03` -must not exist until the CTO separately and explicitly authorizes -implementation against a freshly verified exact `develop` head. Section 23 -defines the lifecycle boundary and section 24 the approval boundary. +Implementation authorization: **separate.** This document specifies BE-03; it +does not authorize it. Implementation required, and received, explicit CTO +authorization against a freshly verified exact `develop` head, separately from +this specification's own approval. Section 23 defines the lifecycle boundary and +section 24 the approval boundary. Specification authoring base: `bcb6ce3081abb14467798b372fcc3e6af9da1c6a` (the merge commit of BE-02 implementation PR @@ -2707,15 +2708,22 @@ Review reasoning level: Extra High / xhigh ## 23. Lifecycle boundary This document is a specification. Its presence on `develop` makes BE-03's -requirements repository-authoritative; it does not create the implementation -branch, authorize an implementation edit, or activate anything. - -BE-03 implementation status is `NOT AUTHORIZED`. The branch -`feature/publisher-services/be-03` must not exist until separate explicit CTO -authorization from a freshly verified base. - -Live review, authorization and merge evidence for the pull request carrying this -content is the GitHub pull-request record and is not copied here (ADR-0005). +requirements repository-authoritative; it did not by itself create the +implementation branch, authorize an implementation edit, or activate anything. +Implementation was separately and explicitly authorized by the CTO from a +freshly verified base, as this boundary requires. + +The BE-03 repository implementation has been delivered as an **inactive +foundation**. Its merge authorized repository integration only. It did not +authorize deployment, environment migration execution, production migration +execution, package commercial backfill, distribution assignment creation or +backfill, durable job creation, dissemination, distribution activation, any +`OBSERVE`/`ENFORCE` transition, workflow change or dispatch, or production +access; each remains separately gated and unauthorized. + +Live review, authorization and merge evidence for the pull requests carrying +this specification and its implementation is the GitHub pull-request record and +is not copied here (ADR-0005). ## 24. Approval boundary diff --git a/docs/publisher-services/README.md b/docs/publisher-services/README.md index fce67b8e..d0c5f757 100644 --- a/docs/publisher-services/README.md +++ b/docs/publisher-services/README.md @@ -1,6 +1,6 @@ # Publisher Services and Distribution Configuration -Status: CONTROL FOUNDATION CLOSED; BE-01 CLOSED; ADR-01-SPEC-AMEND-01 MERGED (PR #781, MERGE COMMIT a511e01c); CORRECTED ADR-01 SPECIFICATION REPOSITORY-AUTHORITATIVE; ADR-01 MERGED - COMPLETE (PR #783, MERGE COMMIT 299b0eff); ADR-0004 AND FINAL PLATFORM INVENTORY APPROVED AND REPOSITORY-AUTHORITATIVE; CG-07 RESOLVED; BE-02 CLOSED - INACTIVE FOUNDATION MERGED THROUGH PR #805; DEPLOYMENT, MIGRATION EXECUTION, BACKFILL AND DISTRIBUTION ACTIVATION NOT AUTHORIZED; ALL OTHER IMPLEMENTATION GATED +Status: CONTROL FOUNDATION CLOSED; BE-01 CLOSED; ADR-01-SPEC-AMEND-01 MERGED (PR #781, MERGE COMMIT a511e01c); CORRECTED ADR-01 SPECIFICATION REPOSITORY-AUTHORITATIVE; ADR-01 MERGED - COMPLETE (PR #783, MERGE COMMIT 299b0eff); ADR-0004 AND FINAL PLATFORM INVENTORY APPROVED AND REPOSITORY-AUTHORITATIVE; CG-07 RESOLVED; BE-02 CLOSED - INACTIVE FOUNDATION MERGED THROUGH PR #805; BE-03 CLOSED - INACTIVE FOUNDATION MERGED THROUGH PR #809; DEPLOYMENT, MIGRATION EXECUTION, BACKFILL, DURABLE JOB CREATION, DISSEMINATION AND DISTRIBUTION ACTIVATION NOT AUTHORIZED; ALL OTHER IMPLEMENTATION GATED Programme owner: CTO Primary coordinating repository: `thoth-pub/thoth` Related repositories: @@ -91,10 +91,17 @@ ADR-0004 APPROVED AND REPOSITORY-AUTHORITATIVE FINAL DISTRIBUTION-PLATFORM INVENTORY APPROVED AND REPOSITORY-AUTHORITATIVE CG-07 RESOLVED BE-02 CLOSED (INACTIVE FOUNDATION MERGED THROUGH PR #805) -BE-03 DEPENDENCIES ON BE-01 AND BE-02 SATISFIED; BE-03 IMPLEMENTATION NOT -AUTHORIZED -DEPLOYMENT, ENVIRONMENT AND PRODUCTION MIGRATION EXECUTION, ASSIGNMENT -CREATION/BACKFILL AND DISTRIBUTION ACTIVATION NOT AUTHORIZED +BE-03 CLOSED (INACTIVE FOUNDATION MERGED THROUGH PR #809) +BE-04 BE-03 DEPENDENCY SATISFIED; BE-04 STILL BLOCKED AND NOT STARTED +MIG-01 BE-03 DEPENDENCY SATISFIED; MIG-01 STILL CRITICAL AND BLOCKED +APP-01 BE-03 BACKEND CONTRACT SATISFIED FOR ITS CONFIGURATION-ONLY SCOPE; +APP-01 STILL BLOCKED BY ITS OTHER CONTROLS; ITS JOB-AWARE ELEMENTS STILL +REQUIRE BE-04 +APP-02 BE-03 DEPENDENCY SATISFIED ONLY; APP-02 STILL BLOCKED ON BE-04 AND +APP-01 +DEPLOYMENT, ENVIRONMENT AND PRODUCTION MIGRATION EXECUTION, PACKAGE +COMMERCIAL BACKFILL, ASSIGNMENT CREATION/BACKFILL, DURABLE JOB CREATION, +DISSEMINATION AND DISTRIBUTION ACTIVATION NOT AUTHORIZED CG-11 UNCHANGED; CG-13 OPEN / UNCHANGED ALL OTHER IMPLEMENTATION REMAINS GATED ``` @@ -231,9 +238,15 @@ Reasons all other implementation remains gated: not authorize deployment, environment or production migration execution, assignment creation or backfill, distribution activation, `OBSERVE`/`ENFORCE` or production access, each of which remains separately - gated. `BE-03`'s `BE-01` and `BE-02` dependencies are therefore satisfied, - and `BE-03` implementation remains `NOT AUTHORIZED` pending its own - approved bounded specification and separate explicit authorization. + gated. `BE-03` is `CLOSED` on the same terms: its bounded implementation + merged through [PR #809](https://github.com/thoth-pub/thoth/pull/809) as an + inactive additive foundation under its own approved bounded specification + and separate explicit implementation authorization. That merge satisfies the + `BE-03` dependency of `BE-04`, `MIG-01`, `APP-01` and `APP-02` without + making any of them ready, and authorizes no deployment, environment or + production migration execution, package commercial backfill, assignment + creation or backfill, durable job creation, dissemination or distribution + activation. 2. Every task still requires its own approved bounded specification, its applicable dependencies, and separate explicit authorization before any implementation branch or edit. @@ -248,8 +261,7 @@ Reasons all other implementation remains gated: Discovery, review, documentation, and read-only orientation may continue. An approved specification makes a task's requirements repository-authoritative; it does not create the implementation branch, authorize an implementation edit, or -unlock `BE-03`, `BE-04`, `APP-01`, OAI-PMH, release, deployment or production -work. +unlock `BE-04`, `APP-01`, OAI-PMH, release, deployment or production work. ## 6. Files diff --git a/docs/publisher-services/decisions.md b/docs/publisher-services/decisions.md index 57f901b9..b4bdbf37 100644 --- a/docs/publisher-services/decisions.md +++ b/docs/publisher-services/decisions.md @@ -1,7 +1,7 @@ # Publisher Services Decision Summary Status: ACTIVE SUMMARY -Last updated: 2026-08-12 (BE-02 closed as an inactive merged foundation; BE-03/BE-04/APP-01 phase boundary raised as a specification candidate under a durable authority condition, including the APP-01 reconciliation) +Last updated: 2026-08-14 (BE-02 and BE-03 closed as inactive merged foundations; the BE-03/BE-04/APP-01 phase boundary's authority condition is satisfied and the decision is approved under its own self-resolving construction, including the APP-01 reconciliation) Owner: CTO This file summarizes decisions. The approved technical design and approved ADRs remain authoritative. @@ -336,9 +336,12 @@ measured and evidenced under This decision candidate **refines and, in that narrow respect, supersedes** the earlier APP-01 wording that assigned superuser back-catalogue-status inspection to a BE-03-only dependency. Nothing else in the approved APP-01 record is -changed: APP-01 remains a `thoth-app` task, remains MEDIUM risk, and remains -blocked on BE-03 exposing the approved protected API, app readiness controls, the -exact-SHA schema pinning control and its own approved bounded specification. +changed: APP-01 remains a `thoth-app` task and remains MEDIUM risk. Its +dependency on BE-03 exposing the approved protected API is **satisfied** for the +configuration-only surface enumerated below, BE-03 having merged that surface; +APP-01 itself remains **blocked** on app readiness controls, the exact-SHA +schema pinning control and its own approved bounded specification, and its +job-aware elements remain dependent on BE-04 as set out below. Scope available from **BE-03 alone** — the BE-03-dependent part of APP-01: diff --git a/docs/publisher-services/rollout-plan.md b/docs/publisher-services/rollout-plan.md index 6cf07328..5066094b 100644 --- a/docs/publisher-services/rollout-plan.md +++ b/docs/publisher-services/rollout-plan.md @@ -119,7 +119,28 @@ BE-02 implementation state (2026-08-12): integration only; deployment, environment and production migration execution, assignment creation or backfill, distribution activation and `OBSERVE`/`ENFORCE` remain separately gated and unauthorized. `BE-03`'s - `BE-02` dependency is satisfied; `BE-03` implementation is `NOT AUTHORIZED`. + `BE-02` dependency is satisfied. + +BE-03 implementation state: + +- `BE-03` is `CLOSED`. The bounded implementation was delivered under its own + approved specification (PR [#808](https://github.com/thoth-pub/thoth/pull/808)) + and separate explicit implementation authorization, and merged into `develop` + through implementation PR + [#809](https://github.com/thoth-pub/thoth/pull/809) as an inactive additive + foundation: the canonical optimistic-concurrency configuration token, the + closed two-value configuration-source type, the append-only configuration + audit table, the single canonical service-configuration write coordinator, + the protected owner-and-superuser read, the superuser-only staff report and + replace mutation, and effective package capability exposure derived from + BE-01's code-owned capability mapping. The migration creates zero audit rows + and changes no package and no assignment. Merge authorized repository + integration only; deployment, environment and production migration execution, + package commercial backfill, assignment creation or backfill, durable job + creation, dissemination, distribution activation and `OBSERVE`/`ENFORCE` + remain separately gated and unauthorized. The `BE-03` dependency of `BE-04`, + `MIG-01`, `APP-01` and `APP-02` is satisfied; none of those tasks becomes + ready, and each retains its remaining blockers. Outstanding evidence: @@ -191,10 +212,13 @@ Controls: ### 2.2 Reserved BE-03/APP-01 GraphQL contract control -Reserved and documented, not implemented. It binds the later `BE-03` and -`APP-01` tasks. +Reserved and documented, not implemented. `BE-03` has merged, so this control +now binds the later `APP-01` task. -1. `BE-03` produces an exact generated GraphQL SDL at its reviewed head. +1. `BE-03` produced an exact generated GraphQL SDL at its reviewed + implementation head, merged through PR + [#809](https://github.com/thoth-pub/thoth/pull/809). This control binds + against that head, not against any later documentation change. 2. `APP-01` records the exact `BE-03` commit SHA. 3. `APP-01` code generation consumes a schema artifact pinned to that SHA, or a preview API proven to expose that exact schema. diff --git a/docs/publisher-services/task-status.md b/docs/publisher-services/task-status.md index 4f0aac90..6b2d7efa 100644 --- a/docs/publisher-services/task-status.md +++ b/docs/publisher-services/task-status.md @@ -4,7 +4,7 @@ Status: ACTIVE TRACKER Programme owner: CTO Master issue: [#765](https://github.com/thoth-pub/thoth/issues/765) Approved design: [private Google Doc](https://docs.google.com/document/d/1kr2Ft0Y4pxgcXGyFAKs_wfFx4I0jlxEvaceswE5Dus8/edit), Drive revision `3` -Last updated: 2026-08-13 (BE-03 specification repository-authoritative on `develop`; BE-03 implementation delivered as a draft pull request, independently reviewed at its previous exact head with a BLOCKED decision, CTO-authorized bounded remediation delivered, and the new exact head awaiting a fresh independent review) +Last updated: 2026-08-14 (BE-03 closed as an inactive merged foundation; the BE-03 dependency recorded as satisfied for BE-04, MIG-01, APP-01 and APP-02 without any of them becoming ready) ## 1. Control rule @@ -25,11 +25,11 @@ No task moves to `READY` without an approved specification, architecture depende | LIC-02 Enforce supported licences | `thoth` | HIGH | BLOCKED | `develop` / `develop` | LIC-01 release; production licence audit plan | #765 | TBD | NOT STARTED | | [BE-01 Publisher package model](../engineering/ai-delivery/tasks/BE-01.md) | `thoth` | HIGH | CLOSED | `develop` at `37b802776ae6853affe19d90156f3c1e0654ebe3` (PR #778 merge commit, verified before any edit) / `develop` | None remaining for BE-01 itself: the separately authorized bounded implementation was delivered on `feature/publisher-services/be-01` under ADR-0003 Architecture A and merged into `develop` through implementation PR [#779](https://github.com/thoth-pub/thoth/pull/779) after fresh independent exact-head review and explicit CTO merge authorization, as required for every HIGH-risk merge. Production migration/release execution remains separately gated by open CG-13, and the MIG-01 commercial backfill remains a separately approved CRITICAL task. | [#765](https://github.com/thoth-pub/thoth/issues/765) | Specification [#774](https://github.com/thoth-pub/thoth/pull/774); implementation [#779](https://github.com/thoth-pub/thoth/pull/779) | CLOSED - INACTIVE FOUNDATION - all publishers `OASIS`; no consumer, package API, mutation, UI, distribution, OAI or Metrics behaviour activated; retained-foundation operational rollback applies; evidence in the [BE-01 implementation report](../engineering/ai-delivery/implementation-reports/BE-01-implementation-report.md) and the immutable exact-head comments on PR #779 | | [BE-02 Distribution platform model](../engineering/ai-delivery/tasks/BE-02.md) | `thoth` | HIGH | CLOSED | `develop` at `1c752a522f7048963efde00b50565379d7c14b4d` (PR #788 merge commit, verified before any edit) / `develop` | None remaining for BE-02 itself: ADR-01/the final inventory is satisfied through PR #783, ADR-0007 through PR #800, and the request-local non-cached DataLoader foundation through PR #802 (`8dcf031d`). The reconciled BE-02 specification was independently reviewed, CTO-approved and merged through PR #788, making it repository-authoritative at `1c752a52`; the CTO then separately authorized implementation against that exact `develop` SHA, and the bounded implementation was delivered on `feature/publisher-services/be-02` and merged into `develop` through implementation PR [#805](https://github.com/thoth-pub/thoth/pull/805) after fresh independent exact-head review and explicit CTO merge authorization, as required for every HIGH-risk merge. Deployment, environment migration execution, production migration, assignment creation/backfill and distribution activation remain separately gated and unauthorized. | #765 | Specification [#788](https://github.com/thoth-pub/thoth/pull/788); implementation [#805](https://github.com/thoth-pub/thoth/pull/805) | CLOSED - INACTIVE FOUNDATION - the 17-value `DistributionPlatform` enum, the `publisher_distribution_platform` migration and repository-authoritative `schema.rs`, the assignment lifecycle, linked OAPEN/DOAB normalization, four additive public GraphQL read surfaces and the first production ADR-0007 DataLoader adoption are merged, with evidence in the [BE-02 implementation report](../engineering/ai-delivery/implementation-reports/BE-02-implementation-report.md) and the immutable exact-head comments on PR #805. The migration creates zero assignment rows, no distribution behaviour is activated, and merge is not deployment, migration execution, backfill or activation authorization | -| [BE-03 Protected service configuration](../engineering/ai-delivery/tasks/BE-03.md) | `thoth` | HIGH | IMPLEMENTATION IN REVIEW | `develop` at `3b6b3a31f9358011f0c998015dfd0c2508380e83` (specification PR #808 merge commit, verified before any edit) / `develop` | BE-01 (CLOSED, satisfied); BE-02 (CLOSED, satisfied). The specification at [`tasks/BE-03.md`](../engineering/ai-delivery/tasks/BE-03.md) is repository-authoritative: its exact CTO-approved content merged into `develop` through PR [#808](https://github.com/thoth-pub/thoth/pull/808) as `3b6b3a31`, which also satisfies the authority condition of the [BE-03/BE-04/APP-01 phase-boundary programme decision](decisions.md) with no separate lifecycle-status edit required. The CTO then separately authorized implementation against that exact `develop` SHA, and the bounded implementation was delivered on `feature/publisher-services/be-03`. An independent HIGH-risk implementation review of the previous exact head `1315057983d389d1ef6b85bc4e69b81eda53aa79` returned BLOCKED on five findings; the CTO resolved the single blocking authority conflict (the actor check-constraint contradiction) and authorized bounded corrections, now delivered on the same branch. Remaining for BE-03 itself: a fresh independent implementation review of the **new** exact head, and explicit CTO merge authorization, as required for every HIGH-risk merge. Deployment, environment migration execution, production migration, assignment creation/backfill and distribution activation remain separately gated and unauthorized. | #765 | Specification [#808](https://github.com/thoth-pub/thoth/pull/808); implementation [#809](https://github.com/thoth-pub/thoth/pull/809) (draft) | IMPLEMENTATION DELIVERED, NOT MERGED - the additive migration (configuration token, closed audit-source type, append-only audit table), repository-authoritative `schema.rs`, the single service-configuration write coordinator, the protected owner-and-superuser read, the superuser-only staff report and replace mutation, derived effective capabilities and the connection-scoped `BE-02` lifecycle refactor are implemented with evidence in the [BE-03 implementation report](../engineering/ai-delivery/implementation-reports/BE-03-implementation-report.md). The migration creates zero audit rows and changes no package or assignment; no distribution job, dissemination or activation exists; and no environment or production migration has been executed | -| BE-04 Durable distribution jobs | `thoth` | HIGH | BLOCKED | `develop` / `develop` | BE-02 (CLOSED, satisfied); BE-03 | #765 | TBD | NOT STARTED | -| MIG-01 Audit/production backfill | `thoth` + operations | CRITICAL | BLOCKED | dedicated task branch -> `develop`; separately approved production run | BE-01 and BE-02 (CLOSED, satisfied); BE-03; licence audit; dry run | #765 | TBD | NOT STARTED | -| APP-01 Service configuration UI | `thoth-app` | MEDIUM | BLOCKED | current `dev` / `dev` pending BR-APP-01 or exception | BE-03 exposing the approved protected API; app readiness controls (BR-APP-01 or explicit CTO exception; the separately specified CG-11 CI closure task); generated API contract pinned to the exact BE-03 commit SHA per the reserved contract control; own approved bounded specification. Scope boundary: under the candidate [BE-03/BE-04/APP-01 phase boundary](decisions.md), BE-03 alone supports only APP-01's configuration scope — own-publisher reads of package, effective capability codes and enabled platforms; superuser read/edit; capability-driven UI affordances; backend-driven linked-platform behaviour; optimistic-concurrency handling; and server-normalized state. APP-01 elements rendering durable back-catalogue job status, attempt state, failure state or pending-onboarding state additionally depend on BE-04 and must not be planned against BE-03 alone | #765 | TBD | NOT STARTED | -| APP-02 Staff subscription report | `thoth-app` | MEDIUM | BLOCKED | current `dev` / `dev` pending BR-APP-01 or exception | BE-03; BE-04; APP-01 | #765 | TBD | NOT STARTED | +| [BE-03 Protected service configuration](../engineering/ai-delivery/tasks/BE-03.md) | `thoth` | HIGH | CLOSED | `develop` at `3b6b3a31f9358011f0c998015dfd0c2508380e83` (specification PR #808 merge commit, verified before any edit) / `develop` | None remaining for BE-03 itself: BE-01 (CLOSED, satisfied) and BE-02 (CLOSED, satisfied). The specification at [`tasks/BE-03.md`](../engineering/ai-delivery/tasks/BE-03.md) is repository-authoritative: its exact CTO-approved content merged into `develop` through PR [#808](https://github.com/thoth-pub/thoth/pull/808) as `3b6b3a31`, which also satisfies the authority condition of the [BE-03/BE-04/APP-01 phase-boundary programme decision](decisions.md) with no separate lifecycle-status edit required. The CTO then separately authorized implementation against that exact `develop` SHA, and the bounded implementation was delivered on `feature/publisher-services/be-03` and merged into `develop` through implementation PR [#809](https://github.com/thoth-pub/thoth/pull/809) after fresh independent exact-head review and explicit CTO merge authorization, as required for every HIGH-risk merge. Post-merge control reconciliation is delivered by [BE-03-CLOSEOUT-01](../engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md). Deployment, environment migration execution, production migration, package commercial backfill, assignment creation/backfill, durable job creation, dissemination and distribution activation remain separately gated and unauthorized. | #765 | Specification [#808](https://github.com/thoth-pub/thoth/pull/808); implementation [#809](https://github.com/thoth-pub/thoth/pull/809) | CLOSED - INACTIVE FOUNDATION - the additive migration (configuration token, closed audit-source type, append-only audit table), repository-authoritative `schema.rs`, the single service-configuration write coordinator, the protected owner-and-superuser read, the superuser-only staff report and replace mutation, derived effective capabilities and the connection-scoped `BE-02` lifecycle refactor are merged, with evidence in the [BE-03 implementation report](../engineering/ai-delivery/implementation-reports/BE-03-implementation-report.md) and the immutable exact-head comments on PR #809. The migration creates zero audit rows and changes no package or assignment; no distribution job, dissemination or activation exists; and merge authorized repository integration only, not deployment, environment or production migration execution, backfill or activation | +| BE-04 Durable distribution jobs | `thoth` | HIGH | BLOCKED | `develop` / `develop` | BE-02 (CLOSED, satisfied); BE-03 (CLOSED, satisfied). BE-04 itself remains unspecified and unauthorized: it requires its own approved bounded specification and separate explicit implementation authorization. BE-03's merge created no `distribution_job`, `distribution_job_target` or `distribution_job_attempt` relation, no automatic back-catalogue job creation and no dissemination; the BE-03 write coordinator is the seam BE-04 will later extend, not a partial BE-04 implementation | #765 | TBD | NOT STARTED | +| MIG-01 Audit/production backfill | `thoth` + operations | CRITICAL | BLOCKED | dedicated task branch -> `develop`; separately approved production run | BE-01, BE-02 and BE-03 (CLOSED, satisfied); licence audit; dry run; the production audit and backfill controls recorded in [`rollout-plan.md`](rollout-plan.md) and open [CG-13](../engineering/repository-map/control-gaps.md). No package commercial backfill and no production migration execution is authorized | #765 | TBD | NOT STARTED | +| APP-01 Service configuration UI | `thoth-app` | MEDIUM | BLOCKED | current `dev` / `dev` pending BR-APP-01 or exception | BE-03 backend contract (CLOSED, satisfied for APP-01's configuration-only scope: the approved protected API is merged and available). APP-01 itself remains BLOCKED by its other controls: app readiness (BR-APP-01 or explicit CTO exception; the separately specified CG-11 CI closure task); a generated API contract pinned to the exact BE-03 commit SHA per the reserved contract control; and its own approved bounded specification. Scope boundary: under the approved [BE-03/BE-04/APP-01 phase boundary](decisions.md), BE-03 alone supports only APP-01's configuration scope — own-publisher reads of package, effective capability codes and enabled platforms; superuser read/edit; capability-driven UI affordances; backend-driven linked-platform behaviour; optimistic-concurrency handling; and server-normalized state. APP-01 elements rendering durable back-catalogue job status, attempt state, failure state or pending-onboarding state additionally depend on BE-04 and must not be planned against BE-03 alone | #765 | TBD | NOT STARTED | +| APP-02 Staff subscription report | `thoth-app` | MEDIUM | BLOCKED | current `dev` / `dev` pending BR-APP-01 or exception | BE-03 (CLOSED, satisfied); BE-04; APP-01. Its satisfied BE-03 dependency does not make APP-02 ready: it remains blocked on BE-04 and APP-01 | #765 | TBD | NOT STARTED | | APP-03 API-backed licence options | `thoth-app` | MEDIUM | BLOCKED | current `dev` / `dev` pending BR-APP-01 or exception | LIC-02 | #765 | TBD | NOT STARTED | | DIS-01 API discovery/comparison | `thoth-dissemination` | HIGH | BLOCKED | `develop` / `develop` | BE-02 (CLOSED, satisfied); MIG-01; BR-DIS-01 or exception | #765 | TBD | NOT STARTED | | DIS-02 Back-catalogue worker | `thoth-dissemination` | CRITICAL | BLOCKED | `develop` / `develop` | BE-04; DIS-01 clean comparison; production controls | #765 | TBD | NOT STARTED | @@ -114,9 +114,10 @@ Each branch starts from the repository's verified development branch and targets delivery-workflow state lives only in that PR's metadata and comments. 6. The merged BE-01 foundation is inactive and closed: every publisher stores `OASIS`, and no consumer, package API, mutation, UI, distribution, OAI or - Metrics behaviour is activated. BE-03 later exposes the protected - package/capability contract under its own approval gates, and the MIG-01 - commercial backfill remains a separately approved CRITICAL task. + Metrics behaviour is activated. BE-03 has since exposed the protected + package/capability contract under its own approval gates, as a merged but + equally inactive foundation, and the MIG-01 commercial backfill remains a + separately approved CRITICAL task. 7. Production migration execution and release for BE-01 remain separately gated by open CG-13; nothing in BE-01 authorizes production action. 8. BE-02 is `CLOSED`. Its dependencies were all satisfied — ADR-01/the final @@ -142,7 +143,7 @@ Each branch starts from the repository's verified development branch and targets 9. The merged BE-02 foundation is inactive and closed: the migration creates zero assignment rows, no publisher has an enabled distribution-platform assignment created by it, and no distribution consumer, job, dissemination - or activation exists. BE-03 later exposes the protected service + or activation exists. BE-03 has since exposed the protected service configuration under its own approval gates. Merge authorized repository integration only; deployment, environment migration execution, production migration, assignment creation or backfill and distribution activation @@ -157,25 +158,22 @@ Each branch starts from the repository's verified development branch and targets approved programme decision with no further status edit required. The CTO separately authorized implementation against that exact freshly verified `develop` head, and the bounded implementation was delivered on - `feature/publisher-services/be-03` as a **draft** pull request following + `feature/publisher-services/be-03` and merged into `develop` through + implementation PR + [#809](https://github.com/thoth-pub/thoth/pull/809) following ADR-0003 Architecture A (direct `thoth-api/src/schema.rs` edit in the same bounded PR as the migration, models, GraphQL contract and tests). Evidence is recorded in the [BE-03 implementation report](../engineering/ai-delivery/implementation-reports/BE-03-implementation-report.md); live review, authorization and merge evidence lives only in that pull - request's record under ADR-0005 and is not restated here. An independent - HIGH-risk implementation review of the previous exact head returned - **BLOCKED** on five findings, one of which was an authority conflict between - the approved specification's exact actor DDL and its own acceptance-test - wording; the CTO resolved that conflict and authorized bounded corrections, - which have been delivered on the same branch without rebase or history - rewrite. BE-03 is **not merged**: the resulting new exact head requires a - **fresh** independent review — the earlier review applies only to the head it - examined — and explicit CTO merge authorization remains outstanding. Merge - would authorize repository integration only — deployment, environment - migration execution, production migration, assignment creation or backfill - and distribution activation remain separately gated and unauthorized. The - specification carried one programme-decision candidate — the + request's record under ADR-0005 and is not restated here. BE-03 is `CLOSED` + as an inactive foundation: merge authorized repository integration only — + deployment, environment migration execution, production migration, package + commercial backfill, assignment creation or backfill, durable job creation, + dissemination and distribution activation remain separately gated and + unauthorized. Post-merge control reconciliation is delivered by + [BE-03-CLOSEOUT-01](../engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md). + The specification carried one programme decision — the [BE-03/BE-04/APP-01 phase boundary](decisions.md), under which BE-03 owns desired configuration only and creates no durable job, no placeholder job and no fabricated job status, and under which APP-01's job-aware elements depend @@ -189,22 +187,25 @@ Each branch starts from the repository's verified development branch and targets production writer, and it implements the protected-read authorization as a least-privilege per-publisher `PUBLISHER_USER` (or superuser) check with no role inheritance, covering package and capability codes alike. -11. APP-01 remains blocked pending BE-03, app readiness controls (BR-APP-01 or - an explicit CTO exception, and the separately specified CG-11 CI closure), - the exact BE-03 SHA/schema-pinning contract control, and its own approved - bounded specification. Under the candidate phase boundary, only APP-01's - configuration scope is satisfiable from BE-03 — including reads of effective - capability codes; durable back-catalogue job status, attempt state, failure - state and pending-onboarding state require BE-04. +11. APP-01's BE-03 backend-contract dependency is satisfied for its + configuration-only scope: the approved protected API is merged and + available. APP-01 itself remains blocked by its other controls — app + readiness (BR-APP-01 or an explicit CTO exception, and the separately + specified CG-11 CI closure), the exact BE-03 SHA/schema-pinning contract + control, and its own approved bounded specification. Under the approved + phase boundary, only APP-01's configuration scope is satisfiable from + BE-03 — including reads of effective capability codes; durable + back-catalogue job status, attempt state, failure state and + pending-onboarding state require BE-04. 12. Beyond the delivered and merged documentation-only ADR-01 implementation, ADR-01-CLOSEOUT-01 control reconciliation, the shared DataLoader - foundation, the merged inactive BE-02 foundation and the separately - authorized, delivered-but-unmerged BE-03 implementation, no BE-04, + foundation and the merged inactive BE-02 and BE-03 foundations, no BE-04, MIG-01, APP-01, APP-02, OAI-PMH, deployment, release, environment or - production migration, assignment creation or backfill, distribution - activation, `OBSERVE`/`ENFORCE` transition or PR #799 action is - authorized; all licence, migration, app, dissemination and operational - tasks remain blocked under their recorded dependencies. Repository - authority, specification work and BE-03 implementation authorization do + production migration, package commercial backfill, assignment creation or + backfill, durable job creation, dissemination, distribution activation, + `OBSERVE`/`ENFORCE` transition, workflow change or manual dispatch, or PR + #799 action is authorized; all licence, migration, app, dissemination and + operational tasks remain blocked under their recorded dependencies. + Repository authority, specification work and a merged implementation do not authorize runtime change, credential use, workflow dispatch or production access. From 41f1d7b91722dd7c96e471748b07c84f8fcff127 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Fri, 14 Aug 2026 08:32:54 +0100 Subject: [PATCH 2/3] docs(publisher-services): clarify closeout evidence record Bounded review remediation for BE-03-CLOSEOUT-01. Additive only; the existing commit is untouched. Finding 1 - correct the ADR-0005 evidence claim. The CHANGELOG entry and implementation report sections 5 and 15 asserted absolutely that no merge commit SHA is transcribed into repository files, which the same change contradicts by legitimately recording b51bcc09 as the exact CTO-authorized implementation base, its identity as PR #812's merge commit, and PR #809's merge commit as ancestry evidence. The wording now distinguishes prohibited terminal-lifecycle transcription - copying GitHub lifecycle metadata merely to restate terminal review, authorization or merge state - from exact SHAs recorded as authorized base or preflight/ancestry evidence, which repository controls require as execution evidence. No exact-base or preflight evidence is removed and BE-03-CLOSEOUT-01.md section 18 is unchanged. Finding 2 - record the actual link-check command. Report section 9 carried a prose description rather than an executable command. It now records the exact reproducible command and its fresh result: 97 relative links checked, 0 broken, re-run after every repository-file edit including these. Also clarifies report section 5.1: the two items are the additional BE-03 source-state hits found by the fresh classified search, distinct from the closeout task record's own Status and section 18 updates that the implementation authorization separately requires. No classification, runtime, schema, migration, workflow or downstream semantics changed. --- CHANGELOG.md | 2 +- ...BE-03-CLOSEOUT-01-implementation-report.md | 104 ++++++++++++++---- 2 files changed, 85 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e8581e1..aa643117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - - `BE-03-CLOSEOUT-01`: correct the materially stale active Publisher Services programme and dependency state left after the `BE-03` implementation merged. Active controls now record `BE-03` as `CLOSED - INACTIVE FOUNDATION`, and stop asserting that `BE-03` is unmerged, a draft, in review, awaiting independent review or merge authorization, `NOT AUTHORIZED`, or that `feature/publisher-services/be-03` must not exist. The `BE-03` dependency is recorded as satisfied for `BE-04`, `MIG-01`, `APP-01` and `APP-02` **without** any of them becoming ready: `BE-04` remains `BLOCKED` and `NOT STARTED` with no `distribution_job`, `distribution_job_target` or `distribution_job_attempt` relation, no automatic back-catalogue job creation and no dissemination in existence; `MIG-01` remains `CRITICAL` and blocked by its audit, backfill and production prerequisites; `APP-01`'s satisfied backend-contract dependency is scoped to its configuration-only surface while its app-readiness controls, exact-SHA contract pinning and own approved specification still gate it and its job-aware elements still require `BE-04`; and `APP-02` remains blocked on `BE-04` and `APP-01`. Corrects the `BE-03` specification's own lifecycle-boundary prose without altering any approved requirement, invariant, architecture, API contract, authorization matrix, migration decision, acceptance criterion or test obligation, and adds the bounded `BE-03-CLOSEOUT-01` implementation report. **Documentation and control records only: no runtime, schema, migration, API, generated contract, client artifact or workflow change.** Under `ADR-0005` no review, approval or merge-authorization identifier, merge commit SHA or merge timestamp is transcribed into repository files, GitHub remains the terminal lifecycle authority, the self-resolving authority-condition construction of the `BE-03`/`BE-04`/`APP-01` phase-boundary decision is preserved as written, and historical implementation-time evidence — including every migration-path reference recorded at an exact implementation head and later renamed by PR [811](https://github.com/thoth-pub/thoth/pull/811) — is preserved unchanged. Deployment, environment and production migration execution, package commercial backfill, assignment creation/backfill, durable job creation, dissemination, distribution activation, `OBSERVE`/`ENFORCE`, workflow changes or dispatch and production access all remain **NOT AUTHORIZED**, and PR [799](https://github.com/thoth-pub/thoth/pull/799), issue [765](https://github.com/thoth-pub/thoth/issues/765) and issue [766](https://github.com/thoth-pub/thoth/issues/766) are untouched + - `BE-03-CLOSEOUT-01`: correct the materially stale active Publisher Services programme and dependency state left after the `BE-03` implementation merged. Active controls now record `BE-03` as `CLOSED - INACTIVE FOUNDATION`, and stop asserting that `BE-03` is unmerged, a draft, in review, awaiting independent review or merge authorization, `NOT AUTHORIZED`, or that `feature/publisher-services/be-03` must not exist. The `BE-03` dependency is recorded as satisfied for `BE-04`, `MIG-01`, `APP-01` and `APP-02` **without** any of them becoming ready: `BE-04` remains `BLOCKED` and `NOT STARTED` with no `distribution_job`, `distribution_job_target` or `distribution_job_attempt` relation, no automatic back-catalogue job creation and no dissemination in existence; `MIG-01` remains `CRITICAL` and blocked by its audit, backfill and production prerequisites; `APP-01`'s satisfied backend-contract dependency is scoped to its configuration-only surface while its app-readiness controls, exact-SHA contract pinning and own approved specification still gate it and its job-aware elements still require `BE-04`; and `APP-02` remains blocked on `BE-04` and `APP-01`. Corrects the `BE-03` specification's own lifecycle-boundary prose without altering any approved requirement, invariant, architecture, API contract, authorization matrix, migration decision, acceptance criterion or test obligation, and adds the bounded `BE-03-CLOSEOUT-01` implementation report. **Documentation and control records only: no runtime, schema, migration, API, generated contract, client artifact or workflow change.** Under `ADR-0005` no active control correction in this change copies GitHub lifecycle metadata — a review, approval or merge-authorization identifier, a merge commit SHA, a merge timestamp or a draft/ready state — merely to restate terminal review, authorization or merge state; the exact SHAs this change records as the authorized implementation base and as preflight/ancestry evidence are execution evidence the repository's own controls require, not post-merge lifecycle transcription. GitHub remains the terminal lifecycle authority, the self-resolving authority-condition construction of the `BE-03`/`BE-04`/`APP-01` phase-boundary decision is preserved as written, and historical implementation-time evidence — including every migration-path reference recorded at an exact implementation head and later renamed by PR [811](https://github.com/thoth-pub/thoth/pull/811) — is preserved unchanged. Deployment, environment and production migration execution, package commercial backfill, assignment creation/backfill, durable job creation, dissemination, distribution activation, `OBSERVE`/`ENFORCE`, workflow changes or dispatch and production access all remain **NOT AUTHORIZED**, and PR [799](https://github.com/thoth-pub/thoth/pull/799), issue [765](https://github.com/thoth-pub/thoth/issues/765) and issue [766](https://github.com/thoth-pub/thoth/issues/766) are untouched - `BE-03-CLOSEOUT-01-SPEC`: propose the bounded post-merge control-correction specification for `BE-03-CLOSEOUT-01` (`docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md`). Records the classified stale-state analysis of the active Publisher Services and shared engineering-control surface after the `BE-03` merge, and specifies the correction that must follow: `BE-03` recorded as `CLOSED - INACTIVE FOUNDATION`; the `BE-03` dependency recorded as satisfied for `BE-04`, `MIG-01`, `APP-01` and `APP-02` **without** any of them becoming ready — `BE-04` remains unspecified and unauthorized with no durable job, target, attempt or automatic onboarding behaviour in existence, `MIG-01` remains `CRITICAL` and blocked by its production audit/backfill prerequisites, `APP-01`'s satisfied backend-contract dependency is scoped to its configuration-only surface while its app-readiness controls, exact-SHA contract pinning and own specification still gate it and its job-aware elements still require `BE-04`, and `APP-02` remains blocked on `BE-04` and `APP-01`. Classifies every statement as `ACTIVE STALE STATE - CORRECT`, `HISTORICAL RECORD - PRESERVE`, `CURRENT AND CORRECT - PRESERVE` or `OUT OF SCOPE - PRESERVE`, forbidding global find/replace. Under `ADR-0005`, forbids any commit that merely transcribes a review, approval or merge-authorization identifier, PR [809](https://github.com/thoth-pub/thoth/pull/809)'s merge SHA or its merge timestamp, and preserves historical implementation-time evidence — including every migration-path reference recorded at an exact implementation head, which the later PR [811](https://github.com/thoth-pub/thoth/pull/811) forward-integration renamed (`BE-02` `20260812_v1.7.0` -> `20260811_v1.7.0`; `BE-03` `20260813_v1.7.0` -> `20260812_v1.7.0`, content and relative apply order preserved). Preserves the `ADR-0005` authority-condition construction of the `BE-03`/`BE-04`/`APP-01` phase-boundary programme decision rather than replacing it with a literal status token, correcting only the references outside that self-resolving construction. **Specification and control records only - no runtime, Cargo, GraphQL, schema, migration, workflow or infrastructure change, no closeout correction performed, and no implementation branch created.** The `BE-03-CLOSEOUT-01` implementation remains **NOT AUTHORIZED** pending explicit CTO authorization against a freshly verified base; `BE-04`, `MIG-01`, `APP-01`, `APP-02`, deployment, environment and production migration execution, package commercial backfill, assignment creation/backfill, durable job creation, dissemination, distribution activation, `OBSERVE`/`ENFORCE`, workflow dispatch, production access and PR [799](https://github.com/thoth-pub/thoth/pull/799) all remain outside scope and unauthorized - `BE-03`: implement the approved bounded **protected publisher service configuration** as an inactive additive foundation. Adds the canonical optimistic-concurrency token `publisher.service_configuration_updated_at` (`timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL`, strictly increasing per publisher through `GREATEST(CURRENT_TIMESTAMP, previous + interval '1 microsecond')`), the closed two-value `publisher_service_configuration_source` type (`SUPERUSER_API`, `MIGRATION_BACKFILL`; no `OTHER`, no `UNKNOWN`, no `Default`) and the append-only `publisher_service_configuration_history` audit table (`actor text NOT NULL` with a named non-whitespace check constraint `CHECK (actor ~ '[^[:space:]]')`, enforcing that an audit actor contains at least one non-whitespace character, `ON DELETE CASCADE` foreign key, and a deterministic `(publisher_id, created_at DESC, id DESC)` composite index), with `thoth-api/src/schema.rs` updated manually and atomically in the same PR under `ADR-0003` Architecture A. Introduces **exactly one authoritative production write path** — the service-configuration write coordinator — which owns every committed write of package, enabled-platform desired state, configuration version token and audit history in one transaction on one connection under an explicit caller-supplied source/actor context, taking the publisher row lock first, rejecting a stale `expectedUpdatedAt` before any validation or lifecycle call, pre-validating the whole normalized desired platform set, applying platform state only through `BE-02`'s lifecycle primitives, committing the package and the token together in **exactly one** publisher `UPDATE` written directly (so no `publisher_history` row is written, and the shared `AFTER UPDATE` work-freshness cascade runs once per committed change whatever its shape, while a true no-op or stale request issues zero publisher `UPDATE`s), and writing exactly one audit row per committed change with bounded three-key canonical before/after state. Refactors `BE-02`'s lifecycle additively into connection-scoped `enable_on`/`disable_on` primitives that return a `#[must_use]` `Changed`/`Unchanged` outcome and validate `is_assignable()` themselves before any write, leaving the pool-level `enable`/`disable` signatures, semantics, early non-assignable check and existing tests unchanged and keeping exactly one linked-platform algorithm in the repository — so a membership-equal but split OAPEN/DOAB pair is **repaired**, bumping the token and writing one audit row, while a fully normalized request is a true no-op that writes nothing. Adds the protected `PublisherServiceConfiguration` type exposing the publisher, `subscriptionPackage`, `effectiveCapabilities`, `enabledDistributionPlatforms` and the version token; effective capabilities are **derived on read** from the canonical package through `BE-01`'s code-owned `ThothPackage::capabilities()` in that slice's order and persisted nowhere, so no package/capability inconsistency is representable and a package change updates them automatically. Adds the owner-and-superuser `publisherServiceConfiguration` query under a least-privilege per-publisher check (superuser, or exactly `PUBLISHER_USER` for that publisher's organisation, with **no role inheritance**: `PUBLISHER_ADMIN`, `WORK_LIFECYCLE` and `CDN_WRITE` without `PUBLISHER_USER` are denied, and a `NULL` `zitadel_id` fails closed for every non-superuser), the superuser-only `publisherServiceConfigurations` staff report and `publisherServiceConfigurationCount` with `[Uuid!] = []`, `[ThothPackage!] = []` and `[DistributionPlatform!] = []` filters, `AND` semantics for `enabledPlatforms`, a mandatory `publisher_id ASC` tie-breaker and a bounded two-statement page (one publisher page plus one `DISTINCT ON` latest-change lookup, with assignments resolved through `BE-02`'s existing request-local `ADR-0007` loader and **no second loader**), and the superuser-only `replacePublisherServiceConfiguration` mutation. Adds exactly one new error variant, `ThothError::StalePublisherServiceConfiguration`, and exactly one new `into_field_error` arm, `STALE_SERVICE_CONFIGURATION`, disclosing no SQL, column name or current token; every other error family keeps its merged mapping. `ThothPackage` and `PublisherCapability` become SDL-reachable for the first time, exclusively through the protected type: neither is on the public `Publisher`, and no package or capability value is anonymously readable. **Accepted and measured consequence:** because the token is a `publisher` column, every committed change — including a platform-only change and a linked-state repair — also moves `publisher.updated_at` and refreshes `work.updated_at_with_relations` for every work of that publisher through the existing `AFTER UPDATE` trigger's single set-based statement (never a per-work application loop), invalidating that publisher's cached export records; a stale request, a true no-op and a rolled-back transaction move none of the three values, and another publisher's works are never touched. **Inactive foundation only: the migration creates zero audit rows and changes no package or assignment; no distribution job, job target, job attempt or fabricated job status exists; no dissemination, upload or feed is produced; no capability state is persisted; no production migration, deployment, environment migration, backfill or distribution activation is performed; mutation-guard mode is unchanged; and no `BE-04`, `MIG-01`, `APP-01`, `APP-02` or PR [799](https://github.com/thoth-pub/thoth/pull/799) work is included.** - `BE-03-SPEC`: propose the complete bounded implementation specification for `BE-03` - **protected service configuration** (`docs/engineering/ai-delivery/tasks/BE-03.md`). Settles the full contract for the protected `PublisherServiceConfiguration` type — which, per `ADR-0001` section 4.4, exposes the current package, the **effective capability codes** and the enabled distribution platforms — the owner-and-superuser `publisherServiceConfiguration` query with its complete deny/allow matrix resolved through the existing ZITADEL publisher-role model (no new ownership table, no new role), the superuser-only paginated and deterministically ordered `publisherServiceConfigurations` staff report with publisher/package/enabled-platform filters declared in the merged repository shape (`[Uuid!] = []`, `[ThothPackage!] = []`, `[DistributionPlatform!] = []`), and the superuser-only `replacePublisherServiceConfiguration` mutation executing in exactly one transaction with a documented deterministic lock order matching `BE-02`. Effective capabilities are **derived on read** from the canonical `subscription_package` through `BE-01`'s code-owned `ThothPackage::capabilities()`, in that mapping's canonical order, and are **persisted nowhere** — no capability column, table, override or cache, no second mapping, and no capability input — so no package/capability inconsistency is representable and a package change updates them automatically; they are protected by the same single read decision as the rest of the type and must not appear on the public `Publisher`. States the protected read as a **least-privilege per-publisher check** — superuser, or exactly `PUBLISHER_USER` for the target publisher's organisation — with **no role inheritance**, so `PUBLISHER_ADMIN`, `WORK_LIFECYCLE` or `CDN_WRITE` without `PUBLISHER_USER` are denied and commercial package visibility is not widened by an unrelated scoped capability. Fixes one authoritative internal **service-configuration write coordinator** owning every committed write of package, enabled-platform desired state, canonical configuration version and configuration audit history in one caller-owned transaction under an explicit source/actor context, with `BE-02`'s pool-level `enable`/`disable` retained unchanged but reclassified as lower-level domain/compatibility functions barred from new production configuration call sites, and required call-site and bypass-search evidence. Selects a **dedicated `publisher.service_configuration_updated_at` concurrency token** with a strict per-publisher monotonicity rule, recording why `publisher.updated_at` and a computed multi-timestamp maximum were rejected, and documenting the accepted consequences that follow from the token being a `publisher` column: `public.publisher` carries **two** existing `UPDATE` triggers, so every committed configuration change — including a platform-only change or a linked-state repair — moves the public `Publisher.updatedAt` through `set_updated_at` **and** refreshes `work.updatedAtWithRelations` for every work of that publisher through its imprints through the existing `AFTER UPDATE` `set_work_updated_at_with_relations`, while a stale request, a true no-op and a rolled-back transaction move none of the three values and no other publisher's works are ever touched. The work-freshness value is a **public downstream signal** that invalidates that publisher's cached export records, so a platform-only change and a linked-state repair newly cause a cascade merged `BE-02` does not cause; the committed transaction therefore writes one publisher row plus bounded configuration/audit rows plus N related work rows through **one set-based trigger statement, never a per-work application loop**, with row-lock footprint and transaction duration growing with catalogue size while the publisher lock is held, and `BE-04` inherits this with the same transaction boundary. The token stays on `publisher` because a separate version table — whose genuine benefit for platform-only persistence is recorded honestly — would not avoid the same cascade for canonical package changes while `BE-01`'s `subscription_package` remains on `publisher`, and eliminating it fully would mean wider changes to approved `BE-01` storage or shared publisher trigger semantics; acceptance is therefore **evidence-conditional**, requiring six-case evidence against a real disposable PostgreSQL database with at least two imprints, at least two target works and a control work of another publisher, plus a catalogue-scale write-amplification and lock-footprint measurement recorded without production extrapolation, and a new stop condition requiring `BLOCKED` and a separate architecture escalation — never a silent trigger or storage change — if that evidence is bad. This freshness cascade is **not** distribution activation: no distribution job, upload, feed or dissemination is created. `Publisher.updatedAt` is explicitly **not** the configuration concurrency token, the protected values themselves stay behind the single read decision (timing correlation is acknowledged rather than denied), and the token's addition to the `Publisher` struct may surface as an additional key in future `publisher_history.data` snapshots; specifies the additive `publisher_service_configuration_history` audit table with an explicit `actor text NOT NULL` column (non-blank check constraint; following the repository's established account-FK-free actor representation but deliberately not named `user_id`, because `source` fixes the actor's provenance) and a closed two-value `source` type whose `SUPERUSER_API`/`MIGRATION_BACKFILL` actor contract is defined now, binding a future `MIG-01` to the same coordinator, the same token update and the same audit invariants while creating no job; plus bounded canonical before/after state that exposes no credential, endpoint, activation identifier or unrelated publisher metadata; requires reuse of `BE-02`'s linked OAPEN/DOAB normalization and non-assignable `JISC_NBK` behaviour through an additive connection-scoped refactor rather than a second implementation, with the primitives reporting whether they changed persisted state so that a **membership-equal but split OAPEN/DOAB pair is repaired rather than skipped** — a repair being a committed change that bumps the token and writes exactly one audit row — and with the connection-scoped enable primitive required to check `is_assignable()` **itself** before any write, as defence in depth alongside the retained pool-level early check and the coordinator's whole-set pre-validation; and requires reuse of `BE-02`'s existing request-local `ADR-0007` assignment DataLoader rather than a second equivalent loader. Raises one **programme-decision candidate** for CTO approval, under a durable `ADR-0005` authority condition rather than a mutable status word — it becomes an approved programme decision when the exact specification content carrying it receives explicit CTO specification approval **and** that content is reachable from `develop`, with no separate lifecycle-status commit required: `BE-03` owns desired configuration only and creates no `distribution_job`, `distribution_job_target` or `distribution_job_attempt` row, no placeholder job and no fabricated job status, with `BE-04` later extending the same transaction boundary; the decision additionally reconciles `APP-01`, whose configuration scope BE-03 satisfies but whose durable job, attempt, failure and pending-onboarding elements require `BE-04`. **Specification and control records only - no runtime, Cargo, GraphQL, schema, migration, workflow or infrastructure change, no implementation, and no implementation branch created.** `BE-03` implementation remains **NOT AUTHORIZED** and `feature/publisher-services/be-03` must not exist; `BE-04`, `MIG-01`, `APP-01`, `APP-02`, deployment, environment and production migration, assignment backfill, distribution activation, `OBSERVE`/`ENFORCE` and PR [799](https://github.com/thoth-pub/thoth/pull/799) all remain outside scope and unauthorized diff --git a/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md b/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md index 71d825c4..3a168d72 100644 --- a/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md +++ b/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md @@ -88,9 +88,19 @@ required. ## 3. Commits -- `docs(publisher-services): reconcile BE-03 post-merge state` - the single - bounded commit carrying this closeout. Its SHA is the branch head recorded in - the pull request. +- `docs(publisher-services): reconcile BE-03 post-merge state` - the bounded + commit carrying this closeout. +- `docs(publisher-services): clarify closeout evidence record` - additive + review-remediation commit. It corrects the overly absolute ADR-0005 evidence + wording in the CHANGELOG entry and in sections 5 and 15 of this report so that + prohibited lifecycle transcription is distinguished from the exact-base and + ancestry SHAs the controls require as execution evidence; records the exact + reproducible relative-link verification command and its fresh result in + section 9 in place of a prose description; and clarifies section 5.1. It + changes no classification, no other file and no scope. The earlier commit was + not amended, rebased or force-pushed. + +The current branch head is recorded in the pull request. ## 4. Files changed @@ -177,14 +187,31 @@ Decisions made within the approved design: says "awaiting review", "pending merge", "draft PR" or "merge authorization outstanding" as current programme state. This closeout therefore does not create the need for another closeout when it merges. -2. **No lifecycle metadata transcribed.** No independent review identifier, CTO - approval identifier, merge-authorization identifier, PR #809 merge commit - SHA or merge timestamp is written into any repository file. Where the - previous prose narrated the BE-03 review history (the earlier BLOCKED - exact-head review and the authorized bounded remediation), that narrative - was removed from the active tracker rather than updated, because ADR-0005 - section 5 makes the GitHub pull-request record the authority for it. Pointers - to PR #808 and PR #809 are retained; they are references, not transcriptions. +2. **No lifecycle metadata transcribed into active control state.** No active + control correction in this change exists to copy an independent review + identifier, a CTO approval identifier, a merge-authorization identifier, a + merge commit SHA, a merge timestamp, a draft/ready state or equivalent + GitHub lifecycle metadata merely to restate terminal review, authorization + or merge state — the transcription ADR-0005 section 4.1 items 6 and 10 + prohibit. Where the previous prose narrated the BE-03 review history (the + earlier BLOCKED exact-head review and the authorized bounded remediation), + that narrative was removed from the active tracker rather than updated, + because ADR-0005 section 5 makes the GitHub pull-request record the + authority for it. Pointers to PR #808 and PR #809 are retained; they are + references, not transcriptions. + + This is distinct from the exact SHAs this change legitimately records. + `BE-03-CLOSEOUT-01.md` section 18 records + `b51bcc0905ac17fc0c142b2002b11fec711331a3` as the exact CTO-authorized + implementation base, and section 1.2 above records that SHA, its identity as + the merge commit of specification PR #812, and PR #809's merge commit + `3ba4452c316399d80cd8d85e7d5e1bd05e252664` as ancestry evidence. Those are + execution evidence required by root `AGENTS.md` to prove implementation + authorization, preflight and repository ancestry — not post-merge lifecycle + transcription — and ADR-0005 does not forbid them. The distinction is + purpose, not SHA-shaped text: recording the base a change was authorized + against proves the change is in scope; copying a merge SHA to announce that + something merged is what the ADR prohibits. 3. **`BE-03.md` corrections confined to the three authorized sites.** The `Status` line uses the house form established by `ADR-01.md` (`APPROVED AND REPOSITORY-AUTHORITATIVE - ...`) rather than a bare @@ -212,7 +239,17 @@ specification's expected set. `platform-inventory.md`, `acceptance-matrix.md`, `master-issue.md` and `control-gaps.md` were searched and left untouched, as expected. -### 5.1 Two fresh findings not present in the authoring-time Annex A +### 5.1 Two additional BE-03 source-state hits found by the fresh search + +These are the two **stale-state findings** the fresh classified search from the +authorized base discovered that the authoring-time Annex A does not record. +They are not the only edits Annex A does not enumerate: the implementation +authorization itself explicitly requires updating the closeout task record's own +`Status` line and its section 18 approval block after specification approval and +implementation authorization. Those task-record updates are directly mandated by +the authorization and are reported in section 4; they are not stale-state +findings and are not classified as such. The two items below are the additional +BE-03 source-state assertions found by the search. Both fall inside an already-expected touched path and inside the approved scope; neither required a new path. @@ -389,20 +426,42 @@ Not applicable to the changed paths. ### Documentation link verification -Command: +Every relative markdown link target in the changed files is resolved against the +filesystem. Absolute (`http:`, `https:`, `mailto:`) targets and same-document +anchors are not filesystem-resolvable and are excluded from the count. -```text -resolve every relative markdown link target in the changed files against the -filesystem +Command, run from the repository root: + +```bash +python3 - <<'PY' +import re, subprocess, os +base = "b51bcc0905ac17fc0c142b2002b11fec711331a3" +files = subprocess.run(["git", "diff", "--name-only", base + "..HEAD"], + capture_output=True, text=True, check=True).stdout.split() +link = re.compile(r'\[[^\]]*\]\(([^)\s]+)\)') +checked = broken = 0 +for f in files: + for t in link.findall(open(f, encoding="utf-8").read()): + if re.match(r'^(https?:|mailto:|#)', t): + continue + checked += 1 + tgt = os.path.normpath(os.path.join(os.path.dirname(f), t.split('#')[0])) + if not os.path.exists(tgt): + broken += 1 + print("BROKEN", f, "->", t) +print("files:", len(files), " relative links checked:", checked, " broken:", broken) +PY ``` Result: ```text -relative links checked: 92 -broken: 0 +files: 8 relative links checked: 97 broken: 0 ``` +Run after every repository-file edit in this task, including the remediation +edits recorded in section 3. + ## 10. Manual verification Environment: local checkout of `feature/publisher-services/be-03-closeout` at @@ -785,8 +844,13 @@ Confirmations: execution, no backfill, no assignment or job creation, no dissemination, no activation, no `OBSERVE`/`ENFORCE` transition, no workflow dispatch and no production access or credential use; -- no review, approval or merge-authorization identifier, merge commit SHA or - merge timestamp was newly transcribed into any repository file. +- no active control correction in this change copies a review, approval or + merge-authorization identifier, a merge commit SHA, a merge timestamp or a + draft/ready state merely to restate terminal review, authorization or merge + state. The exact SHAs recorded here and in `BE-03-CLOSEOUT-01.md` section 18 + — the authorized implementation base and the preflight/ancestry evidence in + section 1.2 — are execution evidence required by repository controls, not + post-merge lifecycle transcription (section 5 item 2). Suggested review focus: From 06cfab5e029a9b951f2512e8fd159c4542035013 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Fri, 14 Aug 2026 09:16:44 +0100 Subject: [PATCH 3/3] docs(publisher-services): clarify closeout acceptance evidence Apply the explicit CTO clarification of one overbroad acceptance criterion in the BE-03-CLOSEOUT-01 task record, and record the clarification in the implementation report. The original criterion forbade any newly transcribed review, approval or merge identifier, merge SHA or merge timestamp regardless of purpose, which conflicted with the task's own purpose-qualified non-goal 2, with ADR-0005's purpose-based prohibition, and with the exact-base and preflight/ancestry evidence the same specification and root AGENTS.md require. Control clarification only: no architecture, runtime scope, BE-03/BE-04/APP-01 boundary, ADR-0005 text, migration policy or downstream authorization changes. --- ...BE-03-CLOSEOUT-01-implementation-report.md | 142 +++++++++++++++++- .../ai-delivery/tasks/BE-03-CLOSEOUT-01.md | 8 +- 2 files changed, 141 insertions(+), 9 deletions(-) diff --git a/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md b/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md index 3a168d72..e5f54f31 100644 --- a/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md +++ b/docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md @@ -99,8 +99,19 @@ required. section 9 in place of a prose description; and clarifies section 5.1. It changes no classification, no other file and no scope. The earlier commit was not amended, rebased or force-pushed. - -The current branch head is recorded in the pull request. +- `docs(publisher-services): clarify closeout acceptance evidence` - additive + control-clarification commit. It applies the explicit CTO clarification of one + overbroad acceptance criterion in this task's own approved specification + (`BE-03-CLOSEOUT-01.md` section 9) and records that clarification here. It + touches those two files only. It changes no architecture, no runtime scope, no + BE-03/BE-04/APP-01 boundary, no ADR-0005 text, no migration policy, no + classification and no other file, and it neither implements nor authorizes any + further work. See section 5.3. The two earlier commits were not amended, + rebased or force-pushed. + +The current branch head is recorded in the pull request. This report records the +commit sequence; the head SHA, review state and merge state are terminal GitHub +evidence under ADR-0005 and are not transcribed here. ## 4. Files changed @@ -165,6 +176,14 @@ The current branch head is recorded in the pull request. durable implementation authorization and the exact authorized base. The header rule "Implementation authorization: **separate.**" is retained unchanged as a durable rule. + - reason (second, later edit): one section 9 acceptance criterion was + overbroad and, read literally, forbade the exact-base and preflight/ancestry + evidence the same specification and root `AGENTS.md` require. The CTO + explicitly clarified it. See section 5.3. + - behavioural effect: none. One checklist item in section 9 is replaced by the + CTO-approved purpose-qualified wording. Section 18's authorized-base + evidence, the historical background, Annex A, the authority condition, + scope, non-goals and architecture are all unchanged. - `docs/engineering/ai-delivery/implementation-reports/BE-03-CLOSEOUT-01-implementation-report.md` - reason: required by the specification section 14 and root `AGENTS.md` @@ -232,7 +251,13 @@ Decisions made within the approved design: inaccurate as a direct consequence of this change; refreshing them follows the BE-02-CLOSEOUT-01 precedent. -Deviations from the specification: NONE. +Deviations from the specification: NONE. There is no implementation deviation +from the CTO-approved specification as clarified. One acceptance criterion's +wording was itself corrected under explicit CTO control before final approval, +because as originally written it was overbroad; the implementation was not +changed to match it and did not need to be. That correction is a +task-specification clarification, not an implementation deviation and not an +architecture amendment. See section 5.3. Scope deviations on touched paths: NONE. The changed set is exactly the specification's expected set. `platform-inventory.md`, `acceptance-matrix.md`, @@ -248,8 +273,10 @@ authorization itself explicitly requires updating the closeout task record's own `Status` line and its section 18 approval block after specification approval and implementation authorization. Those task-record updates are directly mandated by the authorization and are reported in section 4; they are not stale-state -findings and are not classified as such. The two items below are the additional -BE-03 source-state assertions found by the search. +findings and are not classified as such. Neither is the later CTO clarification +of one section 9 acceptance criterion, which is an approved specification +correction recorded in section 5.3. The two items below are the additional BE-03 +source-state assertions found by the search. Both fall inside an already-expected touched path and inside the approved scope; neither required a new path. @@ -318,6 +345,88 @@ and continue to say exactly what they said. The stop condition "if applying this ruling would require changing the BE-03/BE-04/APP-01 architecture, STOP BLOCKED" therefore did not fire. +### 5.3 Section 9 acceptance criterion - CTO control clarification + +The third commit in section 3 applies an explicit CTO clarification to this +task's own approved specification. It is a control clarification only. + +**The defect.** Section 9 of +[`BE-03-CLOSEOUT-01`](../tasks/BE-03-CLOSEOUT-01.md) carried the acceptance +criterion: + +```text +- [ ] no review, approval or merge identifier, merge SHA or merge timestamp is + newly transcribed into a repository file; +``` + +Read literally, that criterion is overbroad. It forbids any newly recorded +review, approval or merge identifier, merge SHA or merge timestamp regardless of +why it is recorded, and so forbids evidence the same repository controls +require. It conflicted with: + +1. this task's own non-goal 2, which is purpose-qualified: it prohibits copying + review, approval and merge-authorization identifiers, PR #809's merge commit + SHA, the merged timestamp or the bare statement "the PR is now merged" into + repository files *merely to transcribe them*; +2. [ADR-0005](../../decisions/ADR-0005-terminal-merge-evidence.md), which + prohibits lifecycle-transcription churn by purpose rather than by textual + shape, and whose section 8 distinguishes a required post-merge correction + from a commit existing merely to record that a pull request merged; +3. the repository requirement to record the exact implementation base and the + preflight and ancestry evidence proving the change was authorized against it + — root [`AGENTS.md`](../../../../AGENTS.md) section 14 requires the exact + base commit in this report, carried in sections 1.1 and 1.2; +4. section 18 of this same specification — already authorized and merged — which + records `b51bcc0905ac17fc0c142b2002b11fec711331a3` as the exact authorized + implementation base. + +Taken literally, the criterion made the document carrying it fail its own test. + +**The ruling.** The CTO explicitly clarified the criterion. The clarified, +CTO-approved wording now in section 9 is: + +```text +- [ ] no active control correction copies a review, approval or + merge-authorization identifier, merge SHA, merge timestamp, draft/ready + state or equivalent GitHub lifecycle metadata merely to restate terminal + review, authorization or merge state; exact SHAs recorded as the + authorized implementation base or as required preflight/ancestry evidence + are permitted execution evidence under repository controls; +``` + +The wording is the CTO's verbatim, including its line breaks. Only the terminal +punctuation is rendered as `;` rather than `.`, so the item matches the +surrounding checklist, whose items are semicolon-separated. No other acceptance +criterion, and no other part of the task record, was touched. + +**What the clarification does not do.** It changes no architecture, no runtime +scope, no BE-03/BE-04/APP-01 boundary and no implementation scope. It does not +alter ADR-0005, migration policy, any other task's recorded status, any +authorization path or any migration. It authorizes no downstream task, no +deployment and no production activity. It is not an architecture amendment. + +**Effect on the implementation.** None. The implementation already drew exactly +the distinction the clarified criterion states — see section 5 item 2 and the +section 15 confirmations, both written before this clarification. The corrected +criterion now matches ADR-0005 and the implementation's already-correct evidence +distinction rather than contradicting both. No control correction in any of the +three commits was changed in order to satisfy the clarification. + +**Three distinct things, kept separate.** This report does not conflate: + +- **approved task-specification clarification** — the CTO-approved correction to + the wording of this task's own acceptance criteria, recorded in this section. + It changes what the task's acceptance test says, not what the implementation + did; +- **implementation remediation** — the additive corrections to repository files + carried by the second and third commits in section 3, made under review and + control feedback without amending, rebasing, squashing or force-pushing + earlier history; +- **GitHub terminal lifecycle evidence** — independent review decisions, CTO + merge authorization, draft/ready state, the merge itself, its SHA and its + timestamp. Under ADR-0005 these live in the GitHub pull-request record and are + deliberately absent from every repository file in this diff. + ## 6. Database and migration effects Migration added: NO @@ -456,7 +565,7 @@ PY Result: ```text -files: 8 relative links checked: 97 broken: 0 +files: 8 relative links checked: 100 broken: 0 ``` Run after every repository-file edit in this task, including the remediation @@ -592,7 +701,11 @@ context, and the search was re-run after the edits. state it exists to correct, including every quotation of the stale wording. These are the approved specification's own content and its acceptance criteria; rewriting them would rewrite the approved specification and - invalidate its own tests. Only `Status` and section 18 were changed. + invalidate its own tests. Preserved. The only changes to this file are + `Status`, section 18, and the single section 9 acceptance criterion the CTO + explicitly clarified — the last being an approved specification clarification + recorded in section 5.3, not a stale-state reclassification of anything in + this list. #### `CURRENT AND CORRECT - PRESERVE` @@ -810,6 +923,14 @@ Monitoring required: none. v1.7.0 publisher-services migrations at `20260811_v1.7.0` and `20260812_v1.7.0`. That is PR #811's business, is out of scope here, and does not affect the BE-02-then-BE-03 apply order. Recorded for the CTO only. +- **Identical overbroad acceptance wording elsewhere, deliberately not edited.** + `docs/engineering/ai-delivery/tasks/BE-02-CLOSEOUT-01.md` carries the same + acceptance criterion that section 5.3 records the CTO as having clarified for + this task. BE-02-CLOSEOUT-01 is a completed task record outside this task's + authorized file set, and the clarification authorization is bounded to the two + files listed against the third commit in section 3. It was therefore not + edited. Recorded so the observation is not lost. Recommended owner: CTO, if + the same clarification is to be applied there. - **`BE-02.md` header.** The BE-02 specification header still reads "Implementation authorization: separate and absent" although BE-02 has merged. It is a BE-02 record, outside this task's scope, and is noted only so the @@ -866,3 +987,10 @@ Suggested review focus: 5. **`BE-03.md` blast radius.** Confirm only the three authorized lifecycle-boundary sites changed and that no requirement, invariant, acceptance criterion, test obligation or BE-04 transaction seam moved. +6. **The section 9 acceptance clarification** (section 5.3). Confirm that the + CTO-approved wording replaced exactly one checklist item, that the + surrounding acceptance criteria, section 18's authorized-base evidence, + Annex A, the authority condition, scope, non-goals and architecture are + unchanged, and that no repository file in this diff now carries a lifecycle + identifier, merge SHA, merge timestamp or draft/ready state recorded merely + to restate terminal review, authorization or merge state. diff --git a/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md b/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md index cd279b0b..fbb97c03 100644 --- a/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md +++ b/docs/engineering/ai-delivery/tasks/BE-03-CLOSEOUT-01.md @@ -383,8 +383,12 @@ touches no environment or production configuration. dependency; - [ ] `docs/publisher-services/decisions.md` section 3a retains its authority-condition construction unchanged; -- [ ] no review, approval or merge identifier, merge SHA or merge timestamp is - newly transcribed into a repository file; +- [ ] no active control correction copies a review, approval or + merge-authorization identifier, merge SHA, merge timestamp, draft/ready + state or equivalent GitHub lifecycle metadata merely to restate terminal + review, authorization or merge state; exact SHAs recorded as the + authorized implementation base or as required preflight/ancestry evidence + are permitted execution evidence under repository controls; - [ ] no migration-path reference in any implementation report is rewritten, and any new prose naming the current BE-03 migration uses `thoth-api/migrations/20260812_v1.7.0/`;