Status
PROPOSED - AWAITING CTO SPECIFICATION APPROVAL
Implementation: NOT AUTHORIZED
Current gate: HOLD
Programme
Publisher Services and Distribution Configuration
Programme stage: Phase C - application interfaces
Parent programme issue: thoth-pub/thoth#765
Repository responsibility
Repository: thoth-pub/thoth-app
thoth-app owns authenticated publisher/staff UI and client behaviour only.
thoth-pub/thoth owns:
- publisher package semantics;
- package capabilities;
- distribution-platform inventory and descriptors;
- linked-platform normalization;
- service-configuration authorization;
- configuration version/concurrency semantics;
- durable distribution-job lifecycle and state;
- the GraphQL schema.
APP-01 must consume those contracts and must not reproduce them as independent frontend policy.
Task identity
Task ID: APP-01
Risk: MEDIUM
Coordination issue: this issue.
Implementation decomposition is proposed before coding:
- APP-01A - v1.7 contract pin and publisher read-only configuration;
- APP-01B - superuser configuration editing and concurrency/error UX;
- APP-01C - truthful latest back-catalogue job presentation.
Each child is an independently implementable repository-local task and therefore requires its own approved issue/specification, exact authorized base SHA, branch and PR.
No implementation branch or PR is authorized by this issue alone.
Current repository baseline
Observed development branch:
dev @ 7a4e7c6ceaec36fbdb201eaeb9ae36985a709889
Observed release/default branch:
main @ 3f2c4a3428641078b820f78c8e08a844b49c71de
Both currently resolve to source tree:
2ea8c49a1936dd25cbea74a749532a32bb6d8399
Observed topology:
dev -> main
Normal task target under the merged root AGENTS.md:
dev
Authorized implementation base SHA:
NONE - implementation is not yet authorized.
Every child implementation must perform a fresh preflight and record the exact dev SHA separately when implementation is explicitly authorized.
Branch-readiness gate
BR-APP-01 remains separate branch-normalization work.
APP-01 requires either:
- completed BR-APP-01; or
- an explicit durable CTO exception permitting APP-01 child tasks to use the current
dev -> feature/... -> dev topology.
The proposed exception does not authorize branch normalization, main promotion, Vercel/provider changes, deployment or production activation.
Upstream contract
Upstream repository: thoth-pub/thoth
Upstream release: v1.7.0
Exact release/source commit:
40e9c06d4ab76217c3ef277dd539d3b5580e2bb8
Exact source tree:
8797558959fcf1f418eb33ca080b469e97783cbd
Backend contracts consumed:
APP-01 must pin the v1.7.0 contract as a whole rather than regenerate against an unpinned moving API.
Exact SDL control
The upstream repository does not commit the generated thoth-client/assets/schema.graphql artifact. The canonical upstream schema generation path is create_schema().as_sdl().
Before APP-01A implementation proceeds:
- generate the GraphQL SDL using the canonical upstream generation path from exactly
40e9c06d4ab76217c3ef277dd539d3b5580e2bb8;
- record the generated SDL SHA-256 in this issue or APP-01A's issue;
- store/use an immutable local contract snapshot as APP-01 codegen input;
- record its provenance: upstream repo,
v1.7.0, commit and tree;
- regenerate
gql/;
- record the complete generated-code diff;
- prove regeneration from the same pinned SDL is clean/deterministic.
Code generation against https://api.test.thoth.pub/graphql is not acceptable evidence of exact v1.7.0 compatibility for APP-01.
If the upstream GraphQL schema changes while APP-01 is in progress, STOP. Do not silently regenerate against the new schema. Perform an explicit compatibility assessment and re-pin only under an approved scope/contract update.
Dependencies
Satisfied upstream source dependencies:
- BE-01: satisfied by v1.7.0;
- BE-02: satisfied by v1.7.0;
- BE-03: satisfied by v1.7.0;
- BE-04: satisfied by v1.7.0 for the job-aware read contract.
Remaining app/readiness dependencies:
- explicit BR-APP-01 completion or CTO branch exception;
- app portion of CG-11 resolved, or an explicit CTO readiness exception;
- exact v1.7.0 SDL generated and digest recorded;
- this APP-01 specification approved;
- child issue/specification approved before each child implementation.
MIG-01
MIG-01 is not a source-code or GraphQL-contract dependency for APP-01 implementation.
It does affect production data population. Until production package/platform backfill is reconciled, APP-01 must render the API's actual current state rather than invent expected legacy configuration.
Production-facing release/activation must separately decide whether MIG-01 completion is required before publisher users should rely on the displayed configuration.
APP-01 must not perform, invoke or simulate MIG-01.
Problem
The v1.7.0 backend now owns authoritative publisher service configuration, including package, effective package capabilities, enabled distribution platforms, linked-platform normalization, optimistic concurrency, and durable distribution-job reporting.
thoth-app currently has no UI consuming this contract.
Publisher users need to see their permitted service configuration. Superusers need a bounded editing interface using the backend's dedicated mutation. Job-aware presentation must show actual BE-04 durable job state and must not derive delivery status from desired configuration.
Scope
Publisher-facing service configuration
For the active authenticated publisher, display:
- current subscription package;
- effective package capabilities returned by the API;
- currently enabled distribution platforms;
- platform display labels and applicable backend-provided metadata;
- read-only service configuration for ordinary publisher users.
Capabilities must be consumed from effectiveCapabilities. Do not implement a package-to-capability matrix in TypeScript.
Platform interaction/display must consume distributionPlatformOptions, including backend-owned linked-group and assignability metadata. Do not maintain an OAPEN/DOAB rule table in the frontend.
Superuser configuration editing
For superusers only, provide controls to replace:
- subscription package;
- enabled distribution platforms.
Mutation: replacePublisherServiceConfiguration.
The mutation request must include the updatedAt value from the exact configuration version the user edited as expectedUpdatedAt.
Package changes must never implicitly add/remove distribution platforms in client code.
Linked platform closure must not be implemented as a second authoritative frontend algorithm. The UI may present the backend linkage clearly, but the submitted state and returned server-normalized state remain authoritative.
After a successful mutation:
- discard any locally assumed final state;
- use the exact mutation response and/or a fresh protected configuration read;
- update/invalidate query state from the server result;
- show success only after the server has accepted the mutation.
Optimistic-concurrency behaviour
The backend GraphQL error classification STALE_SERVICE_CONFIGURATION must be preserved by app GraphQL error plumbing.
On a stale write:
- do not claim success;
- do not automatically overwrite the newer configuration;
- re-read the current configuration;
- clearly tell the user that the configuration changed since they loaded it;
- require a deliberate new edit/retry against the fresh version.
Do not parse human-readable error strings to identify concurrency errors.
Job-creation-disabled behaviour
Automatic distribution-job creation is intended to remain OFF.
The app must not attempt to activate or configure that switch.
When the API rejects a qualifying new automatic-push activation with DISTRIBUTION_JOB_CREATION_DISABLED:
- treat the mutation as failed;
- make clear that the configuration was not saved;
- leave/refetch client state from the API;
- do not show a pending/synthetic onboarding job;
- do not retry automatically.
Job-aware presentation
Where superuser UI displays onboarding/job state, use the actual BE-04 contract.
Use the nullable latestBackCatalogueJob associated with the server's service-configuration report surface.
If no job exists, represent that truthfully, for example:
No back-catalogue onboarding job is recorded.
A null job must never be transformed into:
- success;
- failure;
- pending;
- not required;
- already disseminated;
- not disseminated.
When a job exists, display only API-backed facts useful for staff, such as:
- job status;
- targets;
- attempt count;
- latest bounded worker-reported failure information where present;
- relevant timestamps where useful.
Do not infer dissemination execution or observed remote delivery from a durable job alone.
Maintain these distinctions:
desired configuration != durable distribution job != dissemination execution/observed delivery
Existing app integration
Prefer extending the existing authenticated publisher profile path rather than creating a parallel publisher administration architecture.
Reuse:
/admin/publisher;
- the existing
Profile widget;
- active publisher state from the publisher state machine;
src/entities/publisher Feature-Sliced Design boundaries;
- generated
graphql(...) documents;
GraphqlService;
- TanStack Query hooks;
- existing user/superuser data for UI affordances.
Do not change NextAuth/Zitadel policy.
App GraphQL error plumbing
Current GraphqlService keeps the first GraphQL error message but discards error extensions.
APP-01B may make a narrowly scoped, backwards-compatible enhancement that preserves the stable GraphQL error type for caller inspection while retaining the existing useful message behaviour.
This change must:
- not log bearer tokens or request headers;
- not expose full sensitive GraphQL payloads;
- keep existing callers compatible;
- have focused unit tests;
- avoid introducing backend-specific policy into the shared transport layer beyond preserving server-returned structured error metadata.
Authorization and security invariants
- The Thoth backend remains the authorization authority.
- Hidden controls are presentation only, never an authorization boundary.
- Ordinary publisher users must not receive a superuser mutation path from UI presentation.
- Direct/manual requests remain the backend's responsibility to deny.
- No service/machine credential may be placed in browser code.
- No NextAuth/Zitadel policy or role semantics change is in scope.
- Do not create a frontend role/authorization matrix mirroring backend policy.
- Do not log access tokens, credentials, authorization headers or complete sensitive GraphQL request/response payloads.
- Authorization failures must not leave stale optimistic UI that appears saved.
UI/domain invariants
- No package capability matrix exists in the frontend.
- No independent linked-platform normalization algorithm exists in the frontend.
- No platform eligibility matrix exists in the frontend.
- No distribution-job state machine exists in the frontend.
- No configuration-version semantics are reimplemented in the frontend.
- Server-normalized state wins after every mutation.
- No job is never treated as evidence of dissemination success or failure.
- Package selection never implicitly changes platform assignments in client logic.
- Non-assignable options follow API-provided metadata.
- Existing publisher/staff workflows must not regress.
Proposed implementation decomposition
APP-01A - Contract pin and publisher read-only configuration
Scope:
- capture/pin exact v1.7.0 SDL;
- make codegen deterministic against that pinned artifact;
- regenerate
gql/;
- add
publisherServiceConfiguration query;
- add
distributionPlatformOptions query;
- add entity/service/hooks for reads;
- render current package, effective capabilities and enabled platforms in the existing publisher profile;
- ordinary publisher presentation remains read-only.
No mutation.
No job-status presentation.
No shared GraphQL error plumbing change unless required only to preserve existing behaviour.
APP-01B - Superuser service-configuration editing
Depends on APP-01A.
Scope:
- superuser-only edit controls;
replacePublisherServiceConfiguration;
expectedUpdatedAt;
- server-normalized mutation result;
- stale-write UX;
- job-creation-disabled UX;
- narrowly scoped structured GraphQL error preservation;
- query invalidation/refetch after outcomes.
No backend change.
No job worker.
No job creation.
No provider/runtime configuration.
APP-01C - Truthful back-catalogue job presentation
Depends on APP-01A; may follow APP-01B unless review shows no file overlap.
Scope:
- superuser-only consumption of the existing service-configuration report surface for the active publisher;
- nullable
latestBackCatalogueJob;
- status, targets, attempt/failure data that exists in the API;
- explicit no-job semantics.
No APP-02 report page.
No CSV report/export.
No broad staff filters.
No dissemination execution UI.
No observed-delivery model.
Explicit non-goals
- APP-02 staff subscription/reporting UI;
- APP-03 licence options;
- MIG-01 audit/backfill;
- DIS-01 comparison/cutover;
- DIS-02 worker;
- OAI-PMH;
- changing package/capability semantics;
- changing distribution platform inventory;
- changing linked-platform normalization;
- changing backend authorization;
- changing durable-job lifecycle;
- creating jobs locally;
- activating automatic job creation;
- running migrations;
- provider/Vercel reads or writes;
- deployment;
- production release or activation;
- branch normalization;
- general refactoring of publisher administration.
If implementation starts absorbing any of these, STOP for scope review.
Expected test coverage
APP-01A
- an authorized publisher can render its permitted configuration;
- package comes from protected API configuration;
- capabilities come from
effectiveCapabilities;
- no frontend package-capability lookup exists;
- enabled platforms come from API assignments;
- display/link/assignability metadata comes from
distributionPlatformOptions;
- ordinary publisher UI exposes no editing controls;
- changing active publisher reloads the applicable protected configuration;
- authorization/API failure does not fabricate configuration;
- generated GraphQL types correspond to the exact pinned v1.7.0 SDL;
- rerunning generation from the pinned SDL produces no unexplained generated diff.
APP-01B
- mutation sends the exact configuration token as
expectedUpdatedAt;
- successful mutation replaces client state with the server-normalized result;
- package editing does not implicitly alter platform state in client code;
- backend-linked normalization is reflected from the response;
- ordinary publisher UI exposes no mutation controls;
- backend remains authoritative if a mutation is attempted outside UI controls;
STALE_SERVICE_CONFIGURATION produces explicit stale-write UX and a refresh, with no success state;
- stale writes are never blindly retried;
DISTRIBUTION_JOB_CREATION_DISABLED is shown as a failed/non-saved change;
- authorization/API failures leave client state consistent with the server;
- structured GraphQL error metadata is preserved without regressing existing GraphQL callers.
APP-01C
- a real latest job is rendered from BE-04 state;
- job status is never derived from configured platforms;
- attempt/failure presentation comes only from API fields;
- null latest job renders as no recorded job;
- null latest job does not render success, failure, pending or dissemination status;
- desired configuration and job state remain visually/textually distinct;
- no APP-02 filters/CSV/reporting behaviour is introduced.
Regression/security
- existing publisher profile functionality remains functional;
- non-superusers retain their existing publisher behaviour;
- no token/header/full sensitive payload appears in errors or logs;
- existing auth/session flow remains unchanged.
Required validation
For every applicable child PR, reverify package scripts and run/report:
npm ci
npm run generate
npm run lint
npm test -- --run --coverage
npm run build
Also run focused tests for the changed modules.
The generated-code check must use the exact pinned v1.7.0 SDL.
Any pre-existing lint/test/build/codegen failure must be measured and explicitly separated from a regression introduced by the child task.
GitHub CI coverage is currently insufficient by itself to constitute this validation.
CI/readiness dependency
The app portion of shared control gap CG-11 remains open.
A separate repository-local CI/readiness task should determine the approved GitHub gates for:
- lint;
- production build;
- codegen consistency.
Do not modify .github/workflows/* opportunistically in APP-01.
If the CTO chooses to allow APP-01 implementation before CG-11 is closed, the exception and compensating validation requirements must be explicit and durable before implementation authorization.
Compatibility
Backend compatibility baseline is exactly v1.7.0.
APP-01 must remain compatible while:
THOTH_DISTRIBUTION_JOB_CREATION = OFF
That means:
- reads remain useful;
- package-only changes remain governed by the API;
- pull/manual behaviour remains governed by the API;
- qualifying new automatic-push activation may be rejected by the backend;
- APP-01 reports that rejection truthfully and does not activate the switch.
No client assumes DIS-01 or DIS-02 is deployed.
If the upstream v1.7.0 contract is changed by later backend development, existing APP-01 work continues against the pinned contract until an explicit compatibility decision authorizes a re-pin.
Merge/deployment ordering
Repository/source dependency:
thoth v1.7.0 -> APP-01A -> APP-01B / APP-01C
The upstream source contract is already released.
MIG-01 may proceed independently because it affects data population rather than the APP-01 client contract.
APP-01 may be implemented and merged to thoth-app/dev while automatic distribution-job creation remains OFF.
Each child requires:
implementation -> independent exact-head review -> merge readiness/authorization -> merge to dev
Merge to dev is not production release authorization.
Later:
dev validation -> release readiness -> dev/main promotion -> production observation
remain separate gates.
Any PR-triggered Vercel preview/status creation must be identified as an expected automatic side effect of an authorized PR action. It does not authorize provider reads/writes.
Rollout
Prefer additive UI changes.
Initial dev/preview validation should cover:
- ordinary publisher read-only view;
- superuser read/edit;
- one server-normalized linked-platform response;
- stale-write behaviour;
- authorization failure;
- job-creation-disabled behaviour with no false saved state;
- no-job presentation;
- representative actual job presentation if suitable non-production/test data exists.
No provider/runtime access is implied.
APP-01 must not change THOTH_DISTRIBUTION_JOB_CREATION.
Production release remains separately authorized.
Rollback
Primary rollback is an app-only revert of each bounded APP-01 child PR.
No backend rollback, database migration rollback, distribution-job deletion or dissemination cleanup should be required by APP-01 itself.
If a release needs to be withdrawn, revert/hide the app UI while retaining the additive v1.7.0 backend contract.
HOLD conditions
HOLD if:
- live
dev base cannot be established;
- the branch exception/BR-APP-01 gate is unresolved;
- the APP-01 or child specification is not approved;
- CG-11/readiness has neither closure nor an explicit CTO exception;
- the exact v1.7.0 SDL and digest are not established;
- generated client types do not match the pinned SDL;
- a materially overlapping app PR appears;
- required provider action is not separately authorized.
BLOCKED conditions
BLOCKED if:
- the current backend contract lacks information required to render correct UI state;
- the backend and app authorization models require contradictory behaviour;
- server-normalized platform state cannot be represented without inventing frontend policy;
- correct concurrency handling requires a backend contract change;
- required job state cannot be obtained from BE-04 without fabricating it;
- safe implementation requires an unapproved cross-repository architecture change.
STOP conditions
STOP if:
- APP-01 begins changing package/platform/domain architecture;
- APP-01 begins implementing APP-02 or APP-03;
- APP-01 begins performing MIG-01 work;
- APP-01 begins implementing dissemination/worker behaviour;
- a new reusable cross-programme abstraction is proposed;
- a task attempts to activate distribution-job creation;
- implementation scope expands into auth-policy or provider configuration changes.
Current authorization
Authorized for the current control step:
- read-only repository/GitHub inspection;
- creation of this repository-local APP-01 issue;
- separately authorized chronological linkage/gate comment on parent issue
thoth-pub/thoth#765.
Not authorized:
- source/worktree modification;
- new repository files;
- delete/move/rename;
- branch creation;
- commit;
- push;
- PR creation/update;
- other issue/comment mutation;
- manual CI dispatch/rerun;
- provider/runtime read or write;
- migration execution;
- release/tag/publication;
- merge;
- deployment;
- production activation.
Current gate
HOLD - specification candidate created; implementation is not ready or authorized.
Next actions
- CTO reviews/approves or amends this APP-01 specification and proposed A/B/C decomposition.
- Separately resolve/record the BR-APP-01 exception or complete branch normalization.
- Create/resolve the app-local CG-11 CI/readiness task, or explicitly authorize a temporary readiness exception.
- Capture the exact v1.7.0 SDL digest under separately authorized work.
- Prepare APP-01A with a fresh exact
dev base.
- Only after its own approved child specification and explicit action authorization may APP-01A implementation begin.
Status
PROPOSED - AWAITING CTO SPECIFICATION APPROVAL
Implementation: NOT AUTHORIZED
Current gate: HOLD
Programme
Publisher Services and Distribution Configuration
Programme stage: Phase C - application interfaces
Parent programme issue: thoth-pub/thoth#765
Repository responsibility
Repository:
thoth-pub/thoth-appthoth-appowns authenticated publisher/staff UI and client behaviour only.thoth-pub/thothowns:APP-01 must consume those contracts and must not reproduce them as independent frontend policy.
Task identity
Task ID:
APP-01Risk: MEDIUM
Coordination issue: this issue.
Implementation decomposition is proposed before coding:
Each child is an independently implementable repository-local task and therefore requires its own approved issue/specification, exact authorized base SHA, branch and PR.
No implementation branch or PR is authorized by this issue alone.
Current repository baseline
Observed development branch:
dev @ 7a4e7c6ceaec36fbdb201eaeb9ae36985a709889Observed release/default branch:
main @ 3f2c4a3428641078b820f78c8e08a844b49c71deBoth currently resolve to source tree:
2ea8c49a1936dd25cbea74a749532a32bb6d8399Observed topology:
dev -> mainNormal task target under the merged root
AGENTS.md:devAuthorized implementation base SHA:
NONE - implementation is not yet authorized.
Every child implementation must perform a fresh preflight and record the exact
devSHA separately when implementation is explicitly authorized.Branch-readiness gate
BR-APP-01remains separate branch-normalization work.APP-01 requires either:
dev -> feature/... -> devtopology.The proposed exception does not authorize branch normalization,
mainpromotion, Vercel/provider changes, deployment or production activation.Upstream contract
Upstream repository:
thoth-pub/thothUpstream release:
v1.7.0Exact release/source commit:
40e9c06d4ab76217c3ef277dd539d3b5580e2bb8Exact source tree:
8797558959fcf1f418eb33ca080b469e97783cbdBackend contracts consumed:
APP-01 must pin the v1.7.0 contract as a whole rather than regenerate against an unpinned moving API.
Exact SDL control
The upstream repository does not commit the generated
thoth-client/assets/schema.graphqlartifact. The canonical upstream schema generation path iscreate_schema().as_sdl().Before APP-01A implementation proceeds:
40e9c06d4ab76217c3ef277dd539d3b5580e2bb8;v1.7.0, commit and tree;gql/;Code generation against
https://api.test.thoth.pub/graphqlis not acceptable evidence of exact v1.7.0 compatibility for APP-01.If the upstream GraphQL schema changes while APP-01 is in progress, STOP. Do not silently regenerate against the new schema. Perform an explicit compatibility assessment and re-pin only under an approved scope/contract update.
Dependencies
Satisfied upstream source dependencies:
Remaining app/readiness dependencies:
MIG-01
MIG-01 is not a source-code or GraphQL-contract dependency for APP-01 implementation.
It does affect production data population. Until production package/platform backfill is reconciled, APP-01 must render the API's actual current state rather than invent expected legacy configuration.
Production-facing release/activation must separately decide whether MIG-01 completion is required before publisher users should rely on the displayed configuration.
APP-01 must not perform, invoke or simulate MIG-01.
Problem
The v1.7.0 backend now owns authoritative publisher service configuration, including package, effective package capabilities, enabled distribution platforms, linked-platform normalization, optimistic concurrency, and durable distribution-job reporting.
thoth-appcurrently has no UI consuming this contract.Publisher users need to see their permitted service configuration. Superusers need a bounded editing interface using the backend's dedicated mutation. Job-aware presentation must show actual BE-04 durable job state and must not derive delivery status from desired configuration.
Scope
Publisher-facing service configuration
For the active authenticated publisher, display:
Capabilities must be consumed from
effectiveCapabilities. Do not implement a package-to-capability matrix in TypeScript.Platform interaction/display must consume
distributionPlatformOptions, including backend-owned linked-group and assignability metadata. Do not maintain an OAPEN/DOAB rule table in the frontend.Superuser configuration editing
For superusers only, provide controls to replace:
Mutation:
replacePublisherServiceConfiguration.The mutation request must include the
updatedAtvalue from the exact configuration version the user edited asexpectedUpdatedAt.Package changes must never implicitly add/remove distribution platforms in client code.
Linked platform closure must not be implemented as a second authoritative frontend algorithm. The UI may present the backend linkage clearly, but the submitted state and returned server-normalized state remain authoritative.
After a successful mutation:
Optimistic-concurrency behaviour
The backend GraphQL error classification
STALE_SERVICE_CONFIGURATIONmust be preserved by app GraphQL error plumbing.On a stale write:
Do not parse human-readable error strings to identify concurrency errors.
Job-creation-disabled behaviour
Automatic distribution-job creation is intended to remain OFF.
The app must not attempt to activate or configure that switch.
When the API rejects a qualifying new automatic-push activation with
DISTRIBUTION_JOB_CREATION_DISABLED:Job-aware presentation
Where superuser UI displays onboarding/job state, use the actual BE-04 contract.
Use the nullable
latestBackCatalogueJobassociated with the server's service-configuration report surface.If no job exists, represent that truthfully, for example:
No back-catalogue onboarding job is recorded.A null job must never be transformed into:
When a job exists, display only API-backed facts useful for staff, such as:
Do not infer dissemination execution or observed remote delivery from a durable job alone.
Maintain these distinctions:
desired configuration != durable distribution job != dissemination execution/observed deliveryExisting app integration
Prefer extending the existing authenticated publisher profile path rather than creating a parallel publisher administration architecture.
Reuse:
/admin/publisher;Profilewidget;src/entities/publisherFeature-Sliced Design boundaries;graphql(...)documents;GraphqlService;Do not change NextAuth/Zitadel policy.
App GraphQL error plumbing
Current
GraphqlServicekeeps the first GraphQL error message but discards error extensions.APP-01B may make a narrowly scoped, backwards-compatible enhancement that preserves the stable GraphQL error type for caller inspection while retaining the existing useful message behaviour.
This change must:
Authorization and security invariants
UI/domain invariants
Proposed implementation decomposition
APP-01A - Contract pin and publisher read-only configuration
Scope:
gql/;publisherServiceConfigurationquery;distributionPlatformOptionsquery;No mutation.
No job-status presentation.
No shared GraphQL error plumbing change unless required only to preserve existing behaviour.
APP-01B - Superuser service-configuration editing
Depends on APP-01A.
Scope:
replacePublisherServiceConfiguration;expectedUpdatedAt;No backend change.
No job worker.
No job creation.
No provider/runtime configuration.
APP-01C - Truthful back-catalogue job presentation
Depends on APP-01A; may follow APP-01B unless review shows no file overlap.
Scope:
latestBackCatalogueJob;No APP-02 report page.
No CSV report/export.
No broad staff filters.
No dissemination execution UI.
No observed-delivery model.
Explicit non-goals
If implementation starts absorbing any of these, STOP for scope review.
Expected test coverage
APP-01A
effectiveCapabilities;distributionPlatformOptions;APP-01B
expectedUpdatedAt;STALE_SERVICE_CONFIGURATIONproduces explicit stale-write UX and a refresh, with no success state;DISTRIBUTION_JOB_CREATION_DISABLEDis shown as a failed/non-saved change;APP-01C
Regression/security
Required validation
For every applicable child PR, reverify package scripts and run/report:
Also run focused tests for the changed modules.
The generated-code check must use the exact pinned v1.7.0 SDL.
Any pre-existing lint/test/build/codegen failure must be measured and explicitly separated from a regression introduced by the child task.
GitHub CI coverage is currently insufficient by itself to constitute this validation.
CI/readiness dependency
The app portion of shared control gap CG-11 remains open.
A separate repository-local CI/readiness task should determine the approved GitHub gates for:
Do not modify
.github/workflows/*opportunistically in APP-01.If the CTO chooses to allow APP-01 implementation before CG-11 is closed, the exception and compensating validation requirements must be explicit and durable before implementation authorization.
Compatibility
Backend compatibility baseline is exactly v1.7.0.
APP-01 must remain compatible while:
THOTH_DISTRIBUTION_JOB_CREATION = OFFThat means:
No client assumes DIS-01 or DIS-02 is deployed.
If the upstream v1.7.0 contract is changed by later backend development, existing APP-01 work continues against the pinned contract until an explicit compatibility decision authorizes a re-pin.
Merge/deployment ordering
Repository/source dependency:
thoth v1.7.0 -> APP-01A -> APP-01B / APP-01CThe upstream source contract is already released.
MIG-01 may proceed independently because it affects data population rather than the APP-01 client contract.
APP-01 may be implemented and merged to
thoth-app/devwhile automatic distribution-job creation remains OFF.Each child requires:
implementation -> independent exact-head review -> merge readiness/authorization -> merge to devMerge to
devis not production release authorization.Later:
dev validation -> release readiness -> dev/main promotion -> production observationremain separate gates.
Any PR-triggered Vercel preview/status creation must be identified as an expected automatic side effect of an authorized PR action. It does not authorize provider reads/writes.
Rollout
Prefer additive UI changes.
Initial dev/preview validation should cover:
No provider/runtime access is implied.
APP-01 must not change
THOTH_DISTRIBUTION_JOB_CREATION.Production release remains separately authorized.
Rollback
Primary rollback is an app-only revert of each bounded APP-01 child PR.
No backend rollback, database migration rollback, distribution-job deletion or dissemination cleanup should be required by APP-01 itself.
If a release needs to be withdrawn, revert/hide the app UI while retaining the additive v1.7.0 backend contract.
HOLD conditions
HOLD if:
devbase cannot be established;BLOCKED conditions
BLOCKED if:
STOP conditions
STOP if:
Current authorization
Authorized for the current control step:
thoth-pub/thoth#765.Not authorized:
Current gate
HOLD - specification candidate created; implementation is not ready or authorized.
Next actions
devbase.