Skip to content

feat(sync): bind registered-root reconcile control state (TIN-2864) - #565

Draft
Jesssullivan wants to merge 34 commits into
mainfrom
codex/tin-2864-root-plan-20260719
Draft

feat(sync): bind registered-root reconcile control state (TIN-2864)#565
Jesssullivan wants to merge 34 commits into
mainfrom
codex/tin-2864-root-plan-20260719

Conversation

@Jesssullivan

@Jesssullivan Jesssullivan commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary

Publishes the clean TIN-2864 registered-root reconciliation lane for canonical CI and independent review.

  • binds immutable planner policy and strict reconciliation inputs
  • captures held local snapshots and remote observation resources
  • composes immutable GitRaw/catalog source state
  • closes the source-only catalog publication, mutation-journal, monotonic-fence, and authenticated cold-recovery contracts
  • composes current main and the TIN-2538 GF-only CI-authority source checkpoint

Exact source state

  • signed and GitHub-verified head: 0a3a9ceceeab497af614e07e80e91780c7f3be47
  • head commit: fix(ci): run protected proof on stacked PRs
  • branch: codex/tin-2864-root-plan-20260719
  • draft PR: 34 commits, 44 files, +43,368/-692
  • Neo, Sting, upstream, and live remote are clean and exact at tree 6a1f26d6c00e478cbd007895aa364664d374f9f8

CP21 storage-fence closure

Every authoritative mutable Publishing HEAD, Index, Reservation, Manifest, and committed HEAD write must pass through one retained backend fence.

Each request exact-binds the selected root context, storage/control authorities, writer epoch and writer-fence fingerprints, Pending revision/record, mutation-journal ID and count, ordinal, stage, key, conditional-write predicate, payload length, and BLAKE3. The backend contract must atomically reject a stale fence or apply the exact write at the storage authorization point. Advisory liveness checks, an in-process mutex, or a control read followed by raw OpenDAL I/O do not satisfy it.

Raw rereads are receipt validation only and cannot redeem backend rejection. Exact replay and failure retention cover Pending, Publishing HEAD, namespace mutations, committed HEAD, and Ready.

CP22 authenticated cold reconstruction

A fresh process can now reconstruct one exact canonical PublicationPending epoch without reusing warm planner/executor objects or treating copied bytes as authority.

  • persists and reconstructs the complete predecessor storage binding, including Version+ETag
  • fingerprints the canonical full binding and rejects ETag-only or crossed baselines
  • reacquires an opaque handle to the same durable Pending fence and contiguous receipt ledger
  • preflights aggregate count, key, body, binding, page, root, and per-kind budgets before untrusted bulk reads or retention
  • reconstructs the immutable archived predecessor closure, authoritative journal, successor payloads, and exact unchanged named objects
  • repeats archive/root/page/journal/payload/unchanged-object validation after fence reacquisition and before ordinal zero
  • resumes fresh, partial-prefix, terminal, and third-state cases through authenticated receipt replay only
  • compares recovered committed pages directly to exact expected ordered slices
  • derives canonical Ready bytes/revision and requires terminal ledger/provenance continuity

The adversarial backend fixture now models a one-time exact Ready→Pending CAS. It rejects crossed Ready without state movement and mutates an archived page during reacquisition to prove post-reacquisition rejection with zero receipts, ordinals, or Ready progress.

Claim boundary

This remains SOURCE_ONLY_DIGESTLESS. No production selector, authenticated backend constructor, or live storage-fence implementation exists. The code cannot mint deployed authority, mutate live HEAD or namespace state, emit a plan digest, authorize an action, deploy, activate, reconcile live state, access credentials, enroll a device, or enter a crypto ceremony.

The only direct source-path writes outside the fence are content-addressed absent-only immutable archive, journal, payload, page, and root publications. The fence and reacquisition traits have only cfg(test) implementations.

Exact-head validation

Exact head 0b7b789b121cbbadcc6c970fc6cfa8230ac0cc83 passed on Sting inside the repo-managed nix develop --accept-flake-config shell with the pinned Rust 1.93.0 toolchain:

  • focused publication contract: 60/60
  • tcfs-core unit tests: 44/44
  • tcfs-sync unit tests: 698/698
  • every tcfs-core/tcfs-sync all-target integration test
  • strict affected-crate all-target clippy -D warnings
  • cargo fmt --all -- --check
  • exact predecessor Neo/Sting/upstream/live-remote clean-head and tree seal
  • current exact head 0a3a9ceceeab497af614e07e80e91780c7f3be47: 12/12 CI-authority contract tests, Ruff check/format, JSON/Python parse, local actionlint, Sting diff check, and clean exact tree seal
  • three independent exact-diff Rust, security, and test reviews: no remaining P0/P1

This is strong exact-head local source/build evidence, not durable CI authority.

Durable CI state

Fresh exact-head checks instantiated automatically at 2026-07-25T14:14:55Z on the corrected workflow topology:

  • CI, Nix CI, and CI Live Storage all instantiated at the exact head
  • six executable jobs are queue-bound on sanctioned tinyland-nix / tinyland-dind labels; matrix.surface is intentionally skipped
  • runner assignment and durable authority remain pending live TCFS registration scope
  • no hosted runner or GitHub-capacity fallback is authorized or observed

Both Darwin jobs remain explicitly HELD and deliberately exit nonzero when scheduled. TIN-2998 is Done; TCFS topology integration and durable native authority remain separate gates.

Remaining promotion gates

  • land the sealed authenticated post-Ready acknowledgement slice in stacked PR [TIN-2864] Authenticate post-Ready cold acknowledgement #568 after [TIN-2864] Certify catalog successor layout before publication #567
  • land the sealed byte-aware successor-layout slice in stacked PR [TIN-2864] Certify catalog successor layout before publication #567 after this PR
  • implement the production storage-side fence/gateway and revoke or epoch-fence every raw writer credential/path
  • retain and recheck the exact control guard across final registered-source composition
  • prove Git object presence/kind, reachability, ancestry, fast-forward safety, and enduring writer exclusion
  • add authenticated root selection, cross-root admission, bootstrap/high-water, and all-writer production constructors
  • bind chunk closure and selected-device decryptability; strict manifest parsing still drops version/wrapped-key envelopes after shape validation
  • add conditional-write freshness/backend epoch, credential-epoch rotation, and registered-catalog GC
  • close strict local acquisition beyond Linux

Coordination and holds

This lane owns registered-root planning/publication surfaces in tcfs-core and tcfs-sync. Do not stack unrelated CLI/MCP work onto it; both dirty primary checkouts remain untouched.

TIN-2864 stays In Progress and TIN-2865 remains blocked. TIN-2801 remains the authoritative fleet/live-runtime freeze. TIN-3120/TIN-2538 own durable personal-owner multi-capability listener proof; TIN-2998 owns native Darwin authority.

Keep this PR draft. Do not mark ready or merge until exact-head sanctioned CI is durable, the held Darwin topology is resolved, and the selected landing scope’s review findings are dispositioned. No auto-merge or bypass.

Linear: TIN-2864
Related: TIN-2538, TIN-3120, TIN-2998, TIN-2801

@Jesssullivan

Copy link
Copy Markdown
Owner Author

CP20 source checkpoint: 81911778ca78277d2156f384c0cfca6fda081a40 (signed, pushed).

This adds the source-only authoritative namespace-writer gateway: non-forgeable capability binding to an exact visible publishing-HEAD receipt, retained live backend lease checks before/after every conditional mutation, complete canonical journal execution across Index/Reservation/Manifest, exact replay/collision handling, and terminal/failed evidence that retains authority. Production remains unreachable: no constructor for the retained lease or publishing-HEAD receipt, no live HEAD write/CAS, no finalization/recovery/high-water writer, and no CLI/RPC/action surface.

Exact-source evidence:

  • focused publication tests: 30/30
  • Sting Nix/Rust 1.93 locked workspace tests: pass
  • locked workspace build: pass
  • locked workspace Clippy all targets with -D warnings: pass
  • fmt, diff, conflict-marker scan: pass
  • Neo gitleaks redacted scan: pass
  • Neo↔Sting source SHA-256: a5420c8cb488b3eb81d4219b411f2c81d089f956f03adf80067b043f3f2aa818

PR remains draft and not merge-ready. Hosted checks are exact-head pending, and sanctioned GF exact-head authority remains blocked on TIN-2538 infrastructure.

@Jesssullivan

Copy link
Copy Markdown
Owner Author

Authority-spine source checkpoint: 87e36355ab73afd4c1906765f8ad67553754888d (signed, pushed).

This completes the ordered source-only transaction after CP20:

  • derives and installs visible publishing HEAD with exact predecessor ETag CAS and bounded exact reread
  • executes only the complete fact-bound canonical journal under the retained lease
  • reconstructs unchanged entries from opaque semantic predecessor facts, publishes immutable successor pages/root absent-only, and CASes publishing→committed
  • recovers partial namespace work, still-publishing finalization, and an already-committed closure without LIST or third-state guessing
  • advances PublicationPending → Ready(n+1) through the retained authenticated control backend and preserves exact retry evidence
  • validates committed all-kind Index/Reservation/Manifest catalogs through the production semantic reader

Production remains unreachable: bootstrap, pending-control, retained-lease, and authenticated control authority have no production constructors/implementation. No CLI/RPC/proto/public API, digest, action, deployment, credential, or fleet mutation was added; TIN-2801 remains authoritative.

Exact-source evidence:

  • focused publication tests: 35/35
  • full tcfs-sync lib: 611/611 on Neo
  • Sting Nix/Rust 1.93 locked workspace tests: pass
  • locked workspace build: pass
  • locked workspace Clippy all targets with -D warnings: pass
  • fmt, diff, conflict-marker scan: pass
  • Neo redacted gitleaks: pass
  • Neo↔Sting SHA-256: 7c504bf6a6f5a561bdacd270cd967301556a7523b3e12b12aef5e35a7314b2ca

PR remains draft and not merge-ready. New hosted checks are pending; sanctioned GF exact-head authority remains blocked on TIN-2538 infrastructure. Digest-bound planning/execution remains downstream and TIN-2865 stays blocked.

@Jesssullivan

Copy link
Copy Markdown
Owner Author

CI-authority composition checkpoint: 0b0544b92040ffc6b80ba04550b986e342849474 (signed, pushed).

This cleanly merges the isolated TIN-2538 GF public-read checkpoint bbedd7d84d2faaf798b1420b44c5bcaea8b970ac into the completed TIN-2864 source head. The exact PR head now requests only the sanctioned GF/held authority lanes; Linux source, Nix Linux source, fleet_live, Windows cross-check, and both held native lanes are queued with no runner result yet. The former hosted green matrix is superseded and remains non-authoritative.

Combined-head local evidence: CI-authority contract 11/11, Rust 1.93 Nix devShell cargo check --workspace --locked, fmt, diff check, conflict-marker scan, and redacted gitleaks scan all pass. Local nix flake check --no-build is not claimed: evaluation twice encountered the same invalid/missing /nix/store/...-source path. PR remains draft; no durable-green or merge-ready claim, and no live TCFS ceremony or fleet mutation occurred.

@Jesssullivan

Copy link
Copy Markdown
Owner Author

Exact-head Nix source-realization follow-up: 854d52802881aa6ec72a9685ea8c9622745f4ed5 (signed, pushed).

The one-line fix removes the nested craneLib.path/builtins.path around the filtered flake source. Fresh evaluation failed reproducibly on Neo and Sting before the fix and passes on the exact committed head on Sting without a lazy-tree override. The 11/11 authority contract, fmt, diff check, and redacted history scan also pass; TCFS Rust source is unchanged.

The sanctioned GF/held jobs were re-requested at this exact head and remain queued with no assigned runner. PR remains draft; no durable-green or merge-ready claim, and TIN-2801 live freeze remains authoritative.

@Jesssullivan

Copy link
Copy Markdown
Owner Author

Additional exact-head Sting evidence for 854d52802881aa6ec72a9685ea8c9622745f4ed5: nix build --accept-flake-config --no-link .#tcfsd completed successfully from the fresh filtered source, including the full Crane dependency closure and tcfsd release test phase. Neo and Sting worktrees remain clean and aligned.

This is source/build evidence only. Sanctioned GF/held checks remain queued with no assigned runner, so there is still no durable-green or merge-ready claim.

@Jesssullivan

Copy link
Copy Markdown
Owner Author

Exact-head Sting replay of the complete Linux source authority (GloriousFlywheel) repository command passed for 854d52802881aa6ec72a9685ea8c9622745f4ed5.

Passed under the pinned Nix/Rust 1.93 devShell: authority contract 11/11, locked workspace check, fmt, FileProvider surface contract, clippy all targets with -D warnings, full locked workspace tests, tcfs-sync nats+crypto tests, isolated FileProvider grpc/uniffi and D-Bus grpc tests, both e2e wire-up tests, workspace/k8s-worker/no-FUSE builds, cargo-deny, and redacted exact-range gitleaks. The default and nats+crypto tcfs-sync suites each passed 693 tests.

This is deliberately non-durable source evidence. GitHub still exposes no online tinyland-nix or tinyland-dind runner; TIN-3120 remains the explicit listener/binding blocker. PR stays draft with no merge-ready claim.

@Jesssullivan

Copy link
Copy Markdown
Owner Author

Source-only exact-head update (2026-07-24)

Signed, GitHub-verified head 1c66576a1ad04509d8eba231f43f9fe760ecd5f6 adds a fingerprint-bound 256 MiB aggregate mutation-payload ceiling and a sealed, non-cloneable authoritative batch. Intake now rejects oversized or duplicate bodies transactionally before retention; canonical journals bind and revalidate exact payload-byte accounting; prepared writes share OpenDAL buffers instead of cloning bodies.

Exact evidence on Sting after the final Buffer change:

  • cargo test -p tcfs-core -p tcfs-sync --all-targets — green (tcfs-core 44 unit tests, tcfs-sync 676 unit tests, all affected integration targets)
  • cargo clippy -p tcfs-core -p tcfs-sync --all-targets -- -D warnings — green
  • cargo fmt --all -- --check and git diff --check — green
  • independent source review — SHIP
  • Neo, Sting, and live remote are clean/exact at 1c66576a…; GitHub signature verification is valid

This does not claim the larger P0s are closed: storage-side lease atomicity and authenticated cold-process recovery still need separately bounded source work. The PR remains draft, source-only, digestless, and runtime-inert. Its newly created GloriousFlywheel checks are queued and are not yet durable CI evidence; no hosted-runner fallback is authorized.

Jesssullivan added a commit that referenced this pull request Jul 30, 2026
…(TIN-3278)

The primary state cache holds duplicate entries for the same logical file
under two key namespaces: an absolute canonicalized local path (the form
path_key() always produces on live get/set/mark_conflict today) and a bare
prefix-relative key left behind by an older keying scheme. Live evidence
on neo: secrets/.audit.log tracked at both
/Users/jess/tcfs/secrets/.audit.log (live, conflict record refreshes each
cycle) and /secrets/.audit.log (orphaned, times_recorded frozen at 1881
since 2026-07-07). Because get/set/remove/mark_conflict all re-derive the
key via path_key(), the orphan is never visited by any live read/write
path -- it just sits there forever, double-counted by raw-entry scans like
StateCache::conflicts() ("tcfs conflicts" reporting 9 vs the daemon's
per-cycle plan line reporting conflicts=8).

Root cause: path_key()'s identity fallback (return the input unchanged
when canonicalize fails) makes an unresolvable key indistinguishable from
an already-canonical one. A bare "/secrets/.audit.log" key's parent
("/secrets") does not exist at the filesystem root, so it canonicalizes to
itself and looks canonical even though it never independently resolves.

Fix: keep path_key() as the sole choke point for live writes (unchanged),
and add a load-time migration pass (migrate_duplicate_keys, wired into both
StateCache::open and StateCache::reload_from_disk):

  - resolve_key_on_disk() mirrors path_key() but returns None instead of
    falling back to identity, so migration can tell "canonical" apart from
    "unresolvable".
  - Pass 1 re-keys/merges any key whose independently-resolved form differs
    from its stored key.
  - Pass 2 handles orphans that cannot independently resolve at all: match
    against the other loaded keys using the same suffix convention
    get_by_rel_path() already uses for cross-host lookups. Only an
    unambiguous single match is merged; zero or 2+ candidates leave the
    orphan untouched rather than guess at a target.
  - merge_duplicate_sync_states() joins causal history and never drops a
    conflict record: vector clocks are merged pointwise-max via the
    existing VectorClock::merge (entry vclock, plus same-side joins of a
    merged conflict payload's local_vclock/remote_vclock), because
    partial_cmp_vc reads a dropped component as 0 and would let a peer
    falsely dominate -- classifying RemoteNewer and silently overwriting
    the dropped side's divergence. Scalar fields (blake3/size/mtime/
    chunk_count/remote_path/device_id) have no join, so they still come
    from the higher-last_synced side; if either side carries a conflict the
    merged entry keeps one (later detected_at as payload, times_recorded
    as the max of the two, remote_manifest_key backfilled from the other
    side when missing -- mirroring mark_conflict's preserve-on-missing).
  - Load-time migration is IN-MEMORY ONLY and never marks the cache dirty.
    StateCache::open is reached from read-only CLI paths that hold no
    cross-process StateFileLock (lock_explicit_state_cache only locks when
    a --state override is supplied), and Drop flushes on dirty -- so
    dirtying here would turn "tcfs conflicts" into an unlocked writer whose
    atomic-rename flush can clobber the daemon's concurrent locked update.
    The fold is free for readers; it becomes durable on the next flush by a
    legitimate lock-holding writer (the daemon dirties on any set /
    mark_conflict and flushes the whole map under its own lock). A
    debug_assert pins the invariant at construction.
  - Each merge is logged via tracing::warn! and recorded in a new
    StateCache::key_migration_log() accessor. Reload suppresses records
    already seen in-process, so an orphan that disk keeps reintroducing
    does not re-emit the same warn line every reconcile cycle.
  - One canonicalize attempt per key per call, computed up front and shared
    by both passes, so an unresolvable orphan no longer re-stats every
    candidate on each reload.

Known boundary (documented on migrate_duplicate_keys): the len() != 1
ambiguity guard does not cover a multi-root host where two registered roots
share a relative suffix but only one materializes the file; closing that
needs root-scoped matching, which state-cache keys carry no attribution for
today.

Also adds StateCache::conflicts_naming_unknown_devices(), a read-only scan
for TIN-3278 defect 2 (ghost device ids, e.g. a stale "yoga" string, named
inside a recorded conflict but absent from the caller-supplied known-device
set). Reports only -- never mutates the entry, never touches devices.json
(that migration is TIN-3277 / TIN-1417 territory).

No file-level overlap with the TIN-3277 fix (#576, reconcile.rs only);
trial merge between the two branches is clean. PR #565 (TIN-2864,
Codex-owned) also touches state.rs but in an unrelated region.

Tests (9 TIN-3278 tests, all run on sting):
  - tin3278_dedup_merge_on_load_collapses_duplicate_key_namespaces
  - tin3278_dedup_merge_never_drops_a_conflict_record
  - tin3278_merge_duplicate_sync_states_keeps_richer_conflict_and_max_times_recorded
  - tin3278_merge_joins_vector_clocks_instead_of_dropping_one_side
  - tin3278_merge_joins_conflict_side_clocks_same_side_only
  - tin3278_migration_does_not_dirty_or_rewrite_for_unlocked_readers
  - tin3278_migration_is_idempotent_on_second_load
  - tin3278_ambiguous_orphan_suffix_match_is_left_untouched
  - tin3278_conflicts_naming_unknown_devices_reports_without_mutating

sting: cargo fmt --all --check PASS, cargo test -p tcfs-sync PASS
(571 passed / 0 failed), cargo clippy -p tcfs-sync --all-targets
-D warnings PASS (0 warnings).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant