Skip to content

BE-05 - Deprecate Figshare and Cambridge University Library distribution destinations #840

Description

@ja573

BE-05 - Deprecate Figshare and Cambridge University Library distribution destinations

Status

SPECIFICATION CANDIDATE - REVISED AFTER CONTROL PRE-REVIEW - AWAITING INDEPENDENT REVIEW AND CTO APPROVAL

Implementation: NOT AUTHORIZED

Current gate: HOLD - independent specification review, CTO specification approval and a later fresh exact-base implementation authorization are required. Production assignment/job audit remains a separately authorized later read gate.

This revision resolves two blocking findings found during control pre-review on 2026-08-27:

  1. a 15-row distributionPlatformOptions response cannot truthfully retain the existing GraphQL description saying it returns the "full list of distribution platforms";
  2. opening/updating a Thoth PR may automatically run publish-to-dockerhub and publish a staging PR image to GHCR, so that automatic side effect must be explicit before PR mutation is authorized.

No source, branch, PR, runtime, provider or production mutation is authorized by this specification revision.

1. Task identity

  • Programme: Publisher Services and Distribution Configuration
  • Parent programme issue: thoth-pub/thoth#765
  • Task ID: BE-05
  • Repository: thoth-pub/thoth
  • Programme stage: platform-inventory amendment / controlled retirement
  • Workflow: STANDARD
  • Risk: HIGH
  • Specification baseline: develop @ a6c8cb2016179db635c4bc86ef366aae190829c2
  • Base branch: develop
  • PR target: develop
  • Proposed task branch after implementation authorization: feature/publisher-services/be-05
  • Exact authorized implementation base: NONE - must be freshly established immediately before implementation
  • Owner / implementation agent: not yet assigned
  • Independent reviewer: must be a different agent instance; for HIGH risk prefer a different model/model family
  • Production/runtime effect at this gate: NONE

Namespace preflight at this specification revision found no branch named feature/publisher-services/be-05. This is not implementation authorization and must be repeated immediately before branch creation.

The CTO-approved programme decision of 2026-08-27 retires Figshare and University of Cambridge Library as Thoth distribution services. This issue specifies the bounded backend/source change implementing that decision; the programme decision does not itself authorize implementation, merge, release, deployment, data access or activation.

2. Objective

Retain the stable historical DistributionPlatform identities for Figshare and Cambridge University Library while making both destinations unavailable for new publisher assignment and absent from the public assignment-option list, without deleting historical configuration/location evidence, changing GraphQL executable type shape, or activating automatic distribution-job creation.

JISC_NBK remains deliberately different: it remains a known inactive/non-assignable destination that is still returned as a visible disabled assignment option.

3. Background and authority

Repository-authoritative ADR-0004 and docs/publisher-services/platform-inventory.md currently classify FIGSHARE and CAMBRIDGE_UNIVERSITY_LIBRARY as active, assignable AutomaticPush destinations. Merged code matches that decision: their descriptors are Active + Assignable, DistributionPlatform::ALL contains all 17 stable values, and DistributionPlatformOption::all() currently projects all 17.

The canonical lifecycle already enforces assignability at both the pool-level and connection-scoped enable primitives, and the canonical service-configuration coordinator pre-validates the whole normalized desired set before writes. BE-05 must change the shared code-owned descriptor policy rather than add a second retirement-specific validation path.

Authoritative source seams:

  • docs/engineering/decisions/ADR-0004-distribution-platform-inventory.md
  • docs/publisher-services/platform-inventory.md
  • thoth-api/src/model/publisher_distribution_platform/mod.rs
  • thoth-api/src/model/publisher_distribution_platform/crud.rs (read-only context; no edit expected)
  • thoth-api/src/model/publisher_service_configuration/crud.rs (read-only context; no edit expected)
  • thoth-api/src/graphql/query.rs
  • existing focused model/service-configuration/GraphQL tests

4. Explicit scope

BE-05 must:

  1. retain all 17 stable DistributionPlatform enum values and their serialized/database identities;
  2. make CAMBRIDGE_UNIVERSITY_LIBRARY and FIGSHARE Inactive + NonAssignable;
  3. introduce an internal, code-owned assignment-option visibility policy distinct from assignability/readiness;
  4. hide only Cambridge and Figshare from DistributionPlatformOption::all() while retaining JISC_NBK as visible/non-assignable;
  5. make distributionPlatformOptions return the 15 visible assignment options in canonical relative order;
  6. update the GraphQL field description so it truthfully describes an assignment-option projection rather than the full stable enum inventory;
  7. preserve GraphQL executable shape: same field name, return type, option fields, enum values and nullability;
  8. update ADR-0004 and the current platform inventory to record the approved retirement semantics;
  9. preserve existing canonical read/history behavior for retained retired enum values;
  10. add focused regression tests and a bounded CHANGELOG.md entry.

5. Non-goals

BE-05 must not:

  • delete, rename, renumber or reuse a DistributionPlatform enum value;
  • delete or rewrite existing publisher assignment rows, configuration history, distribution-job rows or historical Location records;
  • add a database migration or edit schema.rs;
  • create a frontend denylist or require app-specific policy logic;
  • edit thoth-app or thoth-dissemination source;
  • alter package/capability semantics, auth policy, distribution-job state-machine behavior or worker logic;
  • execute production reads/writes, direct SQL cleanup, migration/backfill tooling, provider operations or workflow dispatches;
  • enable THOTH_DISTRIBUTION_JOB_CREATION;
  • merge, release, deploy or activate production behavior.

6. Cross-repository impact

Affected contracts:

Contract Impact
database/schema NOT AFFECTED - stable enum/database labels and tables remain unchanged
domain behavior AFFECTED - two descriptors become inactive/non-assignable/hidden from assignment options
GraphQL executable schema shape NOT AFFECTED - same enum values, fields, types and nullability
GraphQL response behavior AFFECTED - distributionPlatformOptions changes from 17 rows to 15
GraphQL descriptions AFFECTED - one field description changes to remain truthful
generated clients/types REMAINS COMPATIBLE - description-only SDL drift and response-subset change require no new type
authorization NOT AFFECTED
export formats NOT AFFECTED
environment/configuration NOT AFFECTED
durable job schema/payload NOT AFFECTED; new activation of the retired destinations becomes impossible through canonical writes
dissemination execution AFFECTED downstream - owned by thoth-pub/thoth-dissemination#101 (DIS-03)
UI assumptions AFFECTED but compatible - owned/verified by thoth-pub/thoth-app#157 (APP-04)

Known direct consumers verified in repository source:

  • thoth-pub/thoth-dissemination consumes distributionPlatformOptions for its pinned Publisher Services platform contract. REQUIRES CHANGE, tracked as DIS-03 / Output to CSV #101. It must not guess this unmerged contract.
  • thoth-pub/thoth-app consumes distributionPlatformOptions. REMAINS SOURCE-COMPATIBLE because its editors render backend-returned option membership generically; integration verification is tracked as APP-04 / Unify docker images with new domain #157.

Compatibility requirement: the stable GraphQL enum and field/type shape remain usable throughout the cross-repository window. Downstream dissemination source must pin the exact merged BE-05 contract before changing its local compatibility map.

Preferred source order:

BE-05 source merge (not production activation) -> DIS-03 pins merged BE-05 contract -> DIS-03 source merge -> separately authorized dissemination release/runtime retirement -> production assignment/job reconciliation -> BE-05 backend production activation -> APP-04 integration verification

7. Invariants

The implementation must preserve:

  1. DistributionPlatform::ALL remains exactly the same 17 values in the same canonical order.
  2. Retired enum values remain parseable/serializable/database-valid and usable for historical reads and reverse lookup.
  3. Historical assignment/audit/location/job evidence is never deleted by this task.
  4. JISC_NBK remains inactive, non-assignable and visible in assignment options.
  5. The existing DistributionPlatformNotAssignable rule remains the single canonical assignment rejection rule.
  6. Whole-set pre-validation remains atomic: a desired set containing any retired/non-assignable destination writes nothing.
  7. Disable/read paths for already-existing retired assignments remain usable so later controlled reconciliation is possible.
  8. Automatic distribution-job creation remains OFF unless separately approved later.
  9. No downstream repository guesses an unmerged upstream contract.

8. Required behavior

8.1 Descriptor policy

Introduce internal Rust vocabulary equivalent to:

AssignmentOptionVisibility::Visible
AssignmentOptionVisibility::Hidden

as a descriptor field/helper. It is deliberately not a GraphQL field and is not inferred from assignment availability or mechanism readiness.

Required outcomes:

Platform Mechanism readiness Assignment availability Assignment-option visibility
CAMBRIDGE_UNIVERSITY_LIBRARY Inactive NonAssignable Hidden
FIGSHARE Inactive NonAssignable Hidden
JISC_NBK Inactive NonAssignable Visible
all other current destinations unchanged unchanged Visible

backCatalogueBehaviour and the retained adapter-profile identity may remain as historical/domain classification. ADR-0004 and the inventory must say explicitly that a retained adapter-profile identity does not assert a currently executable/supported service.

8.2 Visible option projection

DistributionPlatformOption::all() becomes the authoritative visible assignment-options projection:

  • iterate the stable 17-value enum inventory;
  • include only descriptors with visible assignment-option status;
  • preserve canonical relative order;
  • return exactly 15 rows;
  • omit only CAMBRIDGE_UNIVERSITY_LIBRARY and FIGSHARE;
  • retain JISC_NBK with assignable=false.

8.3 Assignment mutation

Reuse DistributionPlatform::is_assignable() and the existing lifecycle/coordinator validation. Do not add a retirement-specific validator.

After BE-05, attempts to enable either retired platform through the low-level supported lifecycle or canonical service-configuration coordinator must return the existing DistributionPlatformNotAssignable classification before any persistent write. Mixed valid+retired complete-set replacements must fail atomically with no package, assignment, audit or durable-job write.

Disable paths remain permitted for retained historical assignments.

8.4 GraphQL compatibility and truthful description

The current QueryRoot::distribution_platform_options description says it returns the "full list of distribution platforms and their metadata". That becomes false when two stable enum identities are deliberately omitted.

Therefore BE-05 must update only that description to wording equivalent to:

Query the visible distribution-platform assignment options and their metadata. Retired stable platform identities may be omitted.

The executable GraphQL contract must otherwise remain unchanged:

  • DistributionPlatform retains all 17 enum values;
  • distributionPlatformOptions keeps the same name and list return type;
  • DistributionPlatformOption keeps the same fields/types/nullability;
  • no new GraphQL visibility/readiness field is introduced.

A byte-identical SDL is not expected after this correction. Required evidence instead is that the generated SDL diff is confined to the intended distributionPlatformOptions description and contains no executable type/field/enum/nullability change.

thoth-app's pinned v1.7 SDL remains executable-compatible and does not need a re-pin or generated-type change merely for a server-side description change and a smaller returned list.

9. Data, migration, auth and operations

  • Database migration required: NO
  • schema.rs change: NO
  • Data/backfill in this source task: NO
  • Authorization change: NO
  • New logs/metrics: NO
  • Provider/runtime access for implementation validation: NO
  • Production assignment/job audit: separate later authorization

10. Required documentation amendment

Update both current repository-authoritative decision surfaces:

  • docs/engineering/decisions/ADR-0004-distribution-platform-inventory.md
  • docs/publisher-services/platform-inventory.md

Record that:

  • the stable inventory remains 17 enum identities;
  • Figshare/Cambridge are retained deprecated identities, inactive, non-assignable and hidden from assignment options;
  • JISC NBK remains visible-but-inactive/non-assignable;
  • the GraphQL assignment-option projection intentionally contains 15 rows while the enum inventory remains 17;
  • dissemination execution is retired separately by DIS-03 / thoth-pub/thoth-dissemination#101;
  • historical rows/locations/audit evidence remain valid historical evidence;
  • automatic distribution-job creation remains OFF.

Do not rewrite historical ADR-01/BE-02 task specifications or implementation reports as if this decision existed at the time.

11. Exact candidate write budget

Existing files permitted:

  • docs/engineering/decisions/ADR-0004-distribution-platform-inventory.md
  • docs/publisher-services/platform-inventory.md
  • thoth-api/src/model/publisher_distribution_platform/mod.rs
  • thoth-api/src/model/publisher_distribution_platform/tests.rs
  • thoth-api/src/model/publisher_service_configuration/tests.rs
  • thoth-api/src/graphql/distribution_platform_tests.rs
  • thoth-api/src/graphql/query.rs - description-only change for distributionPlatformOptions
  • CHANGELOG.md

New files: NONE

Deletion/move/rename: NONE

Explicitly prohibited without specification amendment:

  • database migrations / thoth-api/src/schema.rs
  • GraphQL mutation/type/model source outside the paths listed above
  • generated/pinned downstream app schema artifacts
  • distribution-job state-machine source
  • auth/policy source
  • package/capability source
  • production scripts/data manifests
  • provider/deployment/workflow configuration
  • thoth-dissemination or thoth-app source

If implementation requires another path, return HOLD before editing it.

12. Test-first implementation sequence

  1. Update focused model/GraphQL/service-configuration tests first to express the 17-enum / 15-visible-option contract and prove they fail on the baseline.
  2. Generalize the existing non-assignable tests to cover JISC_NBK, FIGSHARE and CAMBRIDGE_UNIVERSITY_LIBRARY, including mixed valid+retired desired sets and low-level enable rejection.
  3. Add the internal descriptor visibility policy and update only the two retired descriptors plus the default visible state of the remaining inventory.
  4. Change DistributionPlatformOption::all() to filter by descriptor visibility while preserving canonical order.
  5. Change only the distributionPlatformOptions GraphQL description required for truthful API documentation.
  6. Update ADR-0004 and the current platform inventory.
  7. Add the bounded CHANGELOG.md entry under the appropriate Unreleased heading.
  8. Run full validation and prove the SDL executable shape is unchanged apart from the intended description diff.

13. Required acceptance/test evidence

At minimum prove:

  • DistributionPlatform::ALL remains exactly 17 unchanged values in canonical order;
  • string/serde round-trip still supports both retired enum values;
  • CUL/Figshare descriptors are inactive, non-assignable and hidden;
  • JISC is inactive, non-assignable and visible;
  • every other descriptor retains its current readiness/assignability and is visible;
  • DistributionPlatformOption::all() returns exactly 15 values, omitting only CUL/Figshare and retaining JISC;
  • GraphQL distributionPlatformOptions returns the same 15-row projection;
  • the GraphQL enum still contains all 17 platform values;
  • the only SDL change is the approved option-field description wording;
  • direct supported PublisherDistributionPlatform::enable rejects CUL/Figshare/JISC before a write;
  • the canonical configuration coordinator rejects CUL/Figshare/JISC before any write;
  • a mixed valid+retired request is fully rejected with no partial write;
  • disable/read/reverse-lookup behavior remains available for retained historical retired assignments;
  • ordinary valid assignment/disable/linkage behavior remains green;
  • no migration/schema/auth/job-state-machine change exists.

14. Required validation

For the later implementation PR, report at minimum:

git diff --check
cargo fmt --all -- --check
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace

Also capture and review the generated create_schema().as_sdl() diff, requiring that the only SDL change is the approved distributionPlatformOptions description.

No production API/database/provider access is required for source validation.

15. Candidate implementation action-authorization matrix

This matrix is part of the specification only and is NOT active authorization. It becomes usable only if a later CTO implementation-authorization record explicitly adopts it at one exact base SHA.

Action Candidate authorization
repository/GitHub read inspection YES
source/worktree edits within the listed write budget YES
create new files NO
delete/move/rename files NO
branch creation from exact authorized base YES
local validation YES
commit YES
push YES
open/update draft PR YES only if the implementation authorization explicitly acknowledges the automatic CI/container-publication side effect below
issue/comment mutation for task evidence YES
manual CI dispatch/rerun NO
provider/runtime read NO
provider/runtime write NO
migration execution NO
release/tag/publication action NO
merge NO
deployment NO
production activation NO
THOTH_DISTRIBUTION_JOB_CREATION mutation NO

16. Automatic side effects

Live baseline workflow inspection shows:

  • build_test_and_check.yml runs on pull requests and on pushes to develop/master;
  • docker_build_and_push_to_dockerhub.yml runs on pull_request and, when its classifier selects the Docker path, logs into GHCR and pushes a staging-pr-* container image.

Therefore opening/updating a BE-05 PR can have an automatic external container-publication side effect even though the task itself contains no workflow edit. A later implementation authorization that permits PR mutation must explicitly acknowledge/authorize this expected automatic side effect. If that authorization is absent, the implementation agent must stop before opening/updating the PR.

No manual CI dispatch is authorized. No production deployment, migration, provider action or distribution activation is implied by CI or staging-image publication.

17. Production assignment transition - separate later gates

The source change is not safe to activate blindly in production because complete-set replacement validates the whole desired platform set. If a publisher still has CUL/Figshare enabled when those values become non-assignable, a later unrelated replacement that retains the enabled value will fail until it is removed.

Keep these gates distinct:

  1. BE-05 source implementation/review/merge;
  2. DIS-03 source implementation/review/merge;
  3. separately authorized dissemination release/runtime retirement;
  4. separately authorized production read/audit of enabled CUL/Figshare assignments and relevant durable-job state;
  5. disposition of every current assignment/job;
  6. separately authorized production write to disable required assignments through the canonical coordinator/audit path, never ad-hoc SQL by default;
  7. post-write reconciliation showing no unexplained enabled retired assignment;
  8. backend release/deployment/activation of BE-05 behavior;
  9. APP-04 integration verification;
  10. observation/closure.

Pending/running durable jobs must be reconciled through their canonical lifecycle. A RUNNING attempt is not assumed safely cancellable. Production state must be read, not inferred.

THOTH_DISTRIBUTION_JOB_CREATION remains OFF throughout unless a completely separate later activation is approved.

18. Rollout

Initial state after merge to develop: source decision is merged but production behavior is not assumed active.

No feature flag is introduced by BE-05. Production cutover is therefore controlled by deployment/release ordering and the pre-activation assignment/job reconciliation above.

Stop conditions before backend production activation:

  • DIS-03 executable retirement is not production-effective;
  • production assignment/job audit is incomplete;
  • unexplained enabled CUL/Figshare assignment remains;
  • rollback path is not agreed;
  • automatic job-creation state differs from the approved OFF state.

19. Rollback

Before production activation: revert the exact BE-05 source PR if required.

After production assignment reconciliation, a source rollback may re-expose the destinations as assignable options and must not be performed casually. It must account for whether DIS-03 has already removed executable service paths. Do not restore an assignable API/UI state without an executable service merely to reverse source.

No historical data restoration should be required because BE-05 deletes no historical rows.

20. HOLD / STOP

HOLD if:

  • this exact revised specification is not independently reviewed and CTO-approved;
  • the implementation base is not freshly authorized at one exact SHA;
  • develop moves after base authorization;
  • feature/publisher-services/be-05 or a materially overlapping PR appears;
  • another source path becomes necessary;
  • GraphQL executable shape would change beyond the approved description-only drift;
  • production assignment/job state is unknown at activation gate;
  • DIS-03 cannot consume a pinned merged BE-05 contract;
  • safe rollout ordering cannot be established;
  • PR creation would trigger an automatic publication side effect not explicitly covered by the implementation authorization.

STOP if implementation begins:

  • deleting/reusing enum values;
  • adding frontend-specific policy to backend output;
  • direct production SQL cleanup;
  • deleting historical audit/location/configuration evidence;
  • changing unrelated package/auth/job architecture;
  • enabling automatic job creation;
  • dispatching CI manually;
  • merging/releasing/deploying/activating without separate applicable authorization.

21. Expected implementation report and review

The implementing agent must use the canonical implementation-report structure and report exact base/head, commits, files changed, deviations, migration/data/auth effects, validation commands/results, CI/PR state, automatic external effects and remaining gates.

The implementing agent may self-assess but may not approve its own work. HIGH-risk independent source review must be bound to the exact head SHA; a later source commit invalidates approval.

22. Branch and integration plan

  • branch source: freshly authorized exact develop SHA
  • task branch: feature/publisher-services/be-05
  • PR target: develop
  • workflow: STANDARD
  • downstream contract order: BE-05 merge before DIS-03 source implementation
  • branch deletion after merge: YES
  • repository release path: develop -> master, separately controlled
  • merge authorization: separate HIGH-risk CTO gate after exact-head approval

23. Current authorization

Authorized in the current control-plane step:

  • read-only repository/GitHub inspection;
  • issue/specification mutation and bounded coordination comments.

Not authorized now:

  • source/file writes or deletions;
  • branch creation/update;
  • commit/push;
  • PR creation/mutation;
  • manual CI dispatch/rerun;
  • automatic staging-image publication caused by a new PR;
  • production/provider/database read or write;
  • migration execution;
  • release/deployment;
  • merge;
  • production activation;
  • THOTH_DISTRIBUTION_JOB_CREATION mutation.

24. Next action

Obtain independent specification review of this revised exact issue body, then CTO specification approval. After approval, freshly reverify develop, branch/PR overlap, CI side effects and the exact write budget before issuing a separate implementation authorization bound to one exact base SHA.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions