Context
The MST/2 publication model (spec 09) is implemented up to one writer:
src/ceres/snapshot/publication.rs — coordinator core: canonical operation id,
expected-old CAS, read-set predicates, writer-epoch fence, immutable receipt,
outbox, idempotent replay.
src/callisto/mst2_publication.rs, mst2_publication_outbox.rs and
src/jupiter/migration/m20260917_000200_add_mst2_publication.rs — tables
(operation_id unique, per-namespace sequence in mst2_namespace_seq).
MonoStorage::record_publication_in_txn / publication_sequence
(src/jupiter/storage/mono_storage.rs) — bump the namespace sequence with
INSERT … ON CONFLICT … RETURNING, write the receipt and append the outbox
row inside the caller's transaction.
PushQueueService::b3_execute_push_inner (src/jupiter/service/push_queue_service.rs)
— records the publication in the same transaction as the root CAS and
mark_done, which is the trunk-push path.
Everything is behind mst2.publication_enabled (default off), so an
unconfigured deployment is unchanged.
Already covered, do not re-wire: the Web write endpoints (/create-entry,
/edit/save in src/api/router/preview_router.rs) go through
land_api_tip_push → push queue → the same B3 path, so they publish correctly
today.
Scope
Wire the remaining entry points in the spec 09 §5 writer matrix. The pattern in
each case is the same: call record_publication_in_txn inside the
transaction that already performs the visible ref mutation, with a
deterministic operation id.
| Writer |
Entry point |
Transaction to join |
Operation id source |
| CL merge into trunk |
PushQueueService::b3_execute_merge_inner (src/jupiter/service/push_queue_service.rs) |
the merge executor's txn (it writes the root via apply_push_in_txn/descendant advance) |
merge_operation_id(cl_link) (already exists) |
| Repo/kind attach to the monorepo parent |
b3_execute_attach_inner (same file) |
its txn (attach_to_monorepo_parent_in_txn) |
attach_operation_id(repo_id, normalized_commands) (already exists) |
| Import receive-pack |
src/ceres/pack/import_repo.rs (update_refs / finalize path) |
the ref-update transaction for the selected ref |
import push identity (define; must be stable across retries) |
| Import registry add/remove/path change |
import registry service + src/ceres/pack/import_repo.rs |
binding update transaction |
registry revision |
| Tag / release management |
src/api/router/tag_router.rs |
— (see note) |
tag name + target oid |
Note on tags: tags do not advance the served default namespace, so their
publication is only meaningful once the immutable-release policy exists
(spec 09 §5 "tag/release管理"). Treat that row as blocked on the release
policy registry rather than doing it piecemeal.
Note on admin/backfill: any tool that can change a visible root must run
through the same plan; today they bypass it. The deliverable is either (a)
routing them through land_api_tip_push, or (b) refusing to start while
mst2.publication_enabled is true and a maintenance epoch is not held.
Acceptance
- For each wired writer: a test that performs the real operation twice with the
same operation id and asserts one receipt, one sequence advance and one
outbox row (idempotent replay, PUB-11).
- A test that runs two writers concurrently against the same expected-old and
asserts exactly one wins and the loser gets CONFLICT (409) and no ref move.
- A test that injects a failure between the object write and the DB commit and
asserts no publication exists afterwards.
- PUB-01..12 from spec 16 §4, with the writer named in each case.
- Only after all of the above: consider flipping
publication_enabled per the
spec 09 §9 rollout (shadow comparison + maintenance window with all writers
stopped).
References
- Spec 09 §§1–5, §9 (
Mega_ScorpioFS_MST2_Specs_0.2.1, specs/09-…md)
- Spec 16 §4 PUB-01..12
- Existing pattern to copy:
b3_execute_push_inner
Context
The MST/2 publication model (spec 09) is implemented up to one writer:
src/ceres/snapshot/publication.rs— coordinator core: canonical operation id,expected-old CAS, read-set predicates, writer-epoch fence, immutable receipt,
outbox, idempotent replay.
src/callisto/mst2_publication.rs,mst2_publication_outbox.rsandsrc/jupiter/migration/m20260917_000200_add_mst2_publication.rs— tables(
operation_idunique, per-namespace sequence inmst2_namespace_seq).MonoStorage::record_publication_in_txn/publication_sequence(
src/jupiter/storage/mono_storage.rs) — bump the namespace sequence withINSERT … ON CONFLICT … RETURNING, write the receipt and append the outboxrow inside the caller's transaction.
PushQueueService::b3_execute_push_inner(src/jupiter/service/push_queue_service.rs)— records the publication in the same transaction as the root CAS and
mark_done, which is the trunk-push path.Everything is behind
mst2.publication_enabled(default off), so anunconfigured deployment is unchanged.
Already covered, do not re-wire: the Web write endpoints (
/create-entry,/edit/saveinsrc/api/router/preview_router.rs) go throughland_api_tip_push→ push queue → the same B3 path, so they publish correctlytoday.
Scope
Wire the remaining entry points in the spec 09 §5 writer matrix. The pattern in
each case is the same: call
record_publication_in_txninside thetransaction that already performs the visible ref mutation, with a
deterministic operation id.
PushQueueService::b3_execute_merge_inner(src/jupiter/service/push_queue_service.rs)txn(it writes the root viaapply_push_in_txn/descendant advance)merge_operation_id(cl_link)(already exists)b3_execute_attach_inner(same file)txn(attach_to_monorepo_parent_in_txn)attach_operation_id(repo_id, normalized_commands)(already exists)src/ceres/pack/import_repo.rs(update_refs/ finalize path)src/ceres/pack/import_repo.rssrc/api/router/tag_router.rsNote on tags: tags do not advance the served default namespace, so their
publication is only meaningful once the immutable-release policy exists
(spec 09 §5 "tag/release管理"). Treat that row as blocked on the release
policy registry rather than doing it piecemeal.
Note on admin/backfill: any tool that can change a visible root must run
through the same plan; today they bypass it. The deliverable is either (a)
routing them through
land_api_tip_push, or (b) refusing to start whilemst2.publication_enabledis true and a maintenance epoch is not held.Acceptance
same operation id and asserts one receipt, one sequence advance and one
outbox row (idempotent replay, PUB-11).
asserts exactly one wins and the loser gets
CONFLICT(409) and no ref move.asserts no publication exists afterwards.
publication_enabledper thespec 09 §9 rollout (shadow comparison + maintenance window with all writers
stopped).
References
Mega_ScorpioFS_MST2_Specs_0.2.1,specs/09-…md)b3_execute_push_inner