Skip to content

feat(cli)!: replace legacy routing with explicit targets - #1090

Merged
aaltshuler merged 5 commits into
ModernRelay:mainfrom
aaltshuler:codex/cli-target-clean-slate
Oct 20, 2026
Merged

aaltshuler merged 5 commits into
ModernRelay:mainfrom
aaltshuler:codex/cli-target-clean-slate

Conversation

@aaltshuler

@aaltshuler aaltshuler commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What & why

Replace overlapping routing flags and folder/profile fallback with one captured destination: --target NAME|ADDRESS, then defaults.target, otherwise an error. --config supplies source files only. Resolved destinations and known write scopes are delivered to stderr before backend effects; unsupported command/target combinations refuse.

This is the breaking 0.14 CLI migration. It removes legacy routing implementations, selectors, use, profile, positional backend arguments except init URI, and --quiet. target list/show/add/remove edits complete entries; explicit offline target import converts legacy configuration and preserves retry custody. credential get exports a selected endpoint-bound server credential.

The captured binding reaches control storage and native Lance on the current Lance 13 baseline. Provider options preserve native authentication while fixing destination, signing, TLS and conditional-write behavior; unsupported ambient transport overrides refuse even after native environment refill. Endpoint digests use credential scope's canonical identity, and version JSON exposes protocols.target and protocols.credential. Managed identity, same-ID observation, source-free recovery and graph publication retain their existing owners.

The remaining actor classifier and parity-harness cleanup from #1059 is included. RFC 0059, current user examples, embedded skill and breaking release note match the implementation. Access reporting and optional error refinements remain separate. The discontinued second serving model and #1084's MCP work are not included; the existing cluster-backed server remains the sole serving model.

Backing issue / RFC

Checklist

  • Change is focused on the target-based CLI migration
  • Existing owners extended for routing, credentials, native provider selection, diagnostic barriers, actors and retry custody
  • Public docs, embedded skill and permanent breaking note updated
  • Architectural invariants preserved; graph publication, admission and bounded recovery stay with their existing owners

Local verification

After integrating current main/Lance 13:

  • RUST_MIN_STACK=16777216 cargo test -p omnigraph-cli -p omnigraph-server --locked --lib --bin omnigraph-server --test integration: CLI 219 unit + 323 integration passed; server 208 unit + 1 binary + 270 integration passed. Existing ignored journeys remain ignored.
  • Storage owner: 76 passed; core bound-provider owner: 2 passed; native-provider matrix: 9 isolated cases passed. Fake S3/Azure endpoints verify signed reads and conditional creates, capture/drift, cached Azure options, proxy refusals and rotating native credentials.
  • Reproduced failures before fixing canonical HTTP/managed/Unix binding digests, version protocol shape, missing branch diagnostic barriers, ambient conditional-put weakening and default virtual-host S3 endpoint construction. Focused reruns cover each fix.
  • Genuine Lance 11 → candidate → rollback/restore journey passed locally after reproducing and repairing its candidate argument mismatch. The predecessor grammar and all data/index/history/byte-preservation assertions remain unchanged.
  • Real predecessor/candidate migration probe passed: old CLI writes/reads; new CLI refuses legacy config; explicit import preserves backup and rows; the separate old home still works; retired flags refuse.
  • Documentation, AGENTS map, formatting, dependency sources and spelling checks passed. cargo clippy --workspace --all-targets --locked -- -D warnings -W clippy::dbg_macro and the virtual-host endpoint rerun passed. Exact-head CI must pass before merge.

Notes for reviewers

No compatibility routing adapters remain. Older binaries require a separate operator home. Existing graph-format upgrades, omnigraph-server and GQT command lines remain supported. Provider tests do not claim live S3/Azure or real identity-provider qualification; those retain their documented environments and support limits. No storage-cost golden change: option capture adds no storage operations or publication path.

@ragnorc

ragnorc commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

I'm closing #1080 in favour of this one. It's the additive interim; this PR is the accepted breaking design and already carries #1080's target code. Three things from #1080 that this branch doesn't have yet. I can bring them as a patch onto whichever split part owns the CLI grammar:

  1. Typed refusal codes for targets and credentials. feat(cli): name targets in the operator configuration #1080 refuses through CliRefusal with registry codes and a documented table: target_unknown, target_invalid, target_exists, target_is_default, config_not_editable, target_kind_unsupported, credential_terminal, credential_anonymous, credential_missing (178f30e). This branch refuses with untyped strings (targets.rs, target_import.rs). The codes sit in the ErrorCode registry that feat(server)!: say on every error body whether the request ran #1076 introduces and documents, so they fit the CLI part once that lands.
  2. protocols in version --json. It names the version of each machine-readable envelope: target, credential, and later access, serve, local_server_record (178f30e). RFC rfc: graph access and cross-process writes #1017 relies on it: Studio picks a compatible CLI by http_contract, protocols and internal_schema.
  3. A server-target binding digest that matches how requests match endpoints (42d5998, e67386e). Here the digest hashes the raw endpoint string, so https://h.example, https://h.example/, https://h.example:443 and https://H.example are four digests. feat(cli): name targets in the operator configuration #1080 hashes RequestTarget::canonical, which uses the parser's host folding, fills in the default port and drops a trailing slash, and spells a Unix socket path by its bytes, so two non-UTF-8 socket paths don't collide. The binding digest is the identity the local-server election and Studio links compare, so it should be fixed before protocol 1 ships.

schema plan taking a root plus a selected graph here already matches RFC 0059's end state, so #1080's interim refusal of a root target doesn't need to carry over.

The access, serve and mcp PRs (#1081, #1083, #1084) are built on #1080's targets and will be rebased onto this branch's target model once it lands.

@cursor

cursor Bot commented Oct 19, 2026

Copy link
Copy Markdown

Recommendation: request changes. The head reviewed is 84283920f89cc089ae36a3efec72610318bf9634. The PR is open. There is no other review on this head.

Why, what, how, impact

The CLI currently chooses a destination from several flags, a profile, a folder file, and a positional URI. Those selectors do not share one rule, so a command can reach a different backend from the one the operator named.

This PR replaces that with one captured target. The order is --target NAME|ADDRESS, then defaults.target, then an error. --config supplies source files only. target import is the only legacy converter. Every backend command prints the resolved target on stderr before effects. The same captured storage binding is passed to control objects and to Lance.

That is the right shape for a pre-stable break. One binding, one resolution order, and no compatibility adapter removes a class of wrong-destination bugs. The cost is a breaking 0.14 CLI. Scripts that pass --server, --store, --cluster, --profile, use, or --quiet stop working until the operator imports config and updates the command line.

Two protocol-1 behaviors do not match the contract this PR states. A named S3 target still inherits ambient AWS settings that can change signing, TLS, conditional writes, and credential refresh. The published binding hash does not use the same endpoint identity that credential checks already use. Both are cheap to fix before protocol 1 is consumed, and expensive after.

Blocking

1. A named S3 target freezes every parsed AWS_* setting

CapturedStorageBinding::capture copies every AWS_* variable that parses as AmazonS3ConfigKey into the option map, then overwrites region, endpoint, addressing style, and S3 Express.

for (key, value) in env::vars() {
    if key.starts_with("AWS_")
        && let Ok(key) = AmazonS3ConfigKey::from_str(&key.to_ascii_lowercase())
    {
        options.insert(key.as_ref().to_owned(), value);
    }
}
// ... then region, endpoint, virtual_hosted_style, s3_express

Pinned Lance 11.0.0 (lance-io providers/aws.rs) does two things with that map:

  • StorageOptions::with_env_s3 fills only keys that are absent. Keys already copied from the environment stay.
  • build_aws_credential uses aws_access_key_id plus aws_secret_access_key as a static credential. That path does not refresh. The default provider chain runs only when those keys are absent.

object_store 0.13.2 parses these names as real config keys: AWS_SKIP_SIGNATURE, AWS_ALLOW_INVALID_CERTIFICATES (allow_invalid_certificates), AWS_PROXY_URL (proxy_url), AWS_CONDITIONAL_PUT, and the access-key trio. BoundProvider then installs that map as static options and rejects a dynamic provider. The error text says native credential refresh remains available (crates/omnigraph-core/src/lance_access/bound.rs). With static keys in the map, Lance does not refresh.

I ran this on the reviewed head:

CARGO_TARGET_DIR=/workspace/target cargo test -p omnigraph-storage --lib binding::tests::named_s3_capture_copies_unclassified_aws_security_and_static_keys -- --exact --nocapture

A named destination of region us-east-1 and endpoint https://s3.us-east-1.amazonaws.com captured:

  • aws_skip_signature=true
  • proxy_url=http://proxy.example:8080
  • allow_invalid_certificates=true
  • aws_conditional_put=etag
  • aws_access_key_id, aws_secret_access_key, and aws_session_token

The declared region and endpoint did win over ambient region and endpoint. Signing, TLS verification, the proxy, conditional-put mode, and static credentials did not. The control adapter and Lance both receive this map, so the two paths agree, and both can leave the named account.

RFC 0059 requires each provider option to be classed as destination, authentication, or transport before acceptance. An omitted destination option has a fixed default or the command refuses. Azure from_config already forces account, endpoint, use_emulator=false, and use_fabric_endpoint=false after it reads the environment. S3 has no equivalent force-off for signature, TLS, proxy, or conditional put.

The violated invariant is one source of truth for a destination. The affected class is every named or inline S3 open in a process whose environment carries an unclassified AWS_* key, including a long cluster apply --wait or export that holds an expiring session token.

Fix the cause in CapturedStorageBinding::capture: an allow-list of authentication keys, explicit values for destination and safety keys (skip_signature=false, allow_invalid_certificates=false, no proxy unless the target declares one, conditional-put left at the provider default), and no static access key unless the target asked for static credentials. Keep the refresh chain for the normal case. Add a storage test that fails if those unclassified keys appear. GQT cannot see a provider option map. omnigraph-storage binding tests are the owner. I removed the temporary probe after the run.

Debug for CapturedStorageBinding and Lance StorageOptionsAccessor does not print option values. I did not find a log line that emits the map. Credential files are still created mode 0600, and credential get refuses a terminal. This finding is about authority, not about a token printed in an error.

2. The protocol-1 binding hash is not the endpoint identity requests use

TargetBinding::digest hashes the endpoint string as stored (crates/omnigraph-cli/src/targets.rs, digest). Credential scope uses RequestTarget, which takes the URL parser's host, fills the default port, and drops a trailing empty segment (crates/omnigraph-cli/src/graph_http.rs, RequestTarget::of). This branch has no canonical() method. Closed #1080 hashes RequestTarget::canonical and locks the spellings in a_binding_digest_names_where_a_target_points_and_nothing_else.

The url crate on this toolchain folds these four spellings to host h.example and port 443:

  • https://h.example
  • https://h.example/
  • https://h.example:443
  • https://H.example

https://h.example:8443 stays port 8443. Credential checks treat the first four as one endpoint. The published binding field treats them as four hashes. A percent-encoded Unix socket has the same split: the matcher uses decoded path bytes, and the hash uses the raw string.

target list|show --json already publishes that hash under protocol: 1. Local-server election and Studio links (#1083, RFC #1017) are specified to compare it. Shipping protocol 1 on the raw string makes a later canonical hash a break.

Hash RequestTarget::canonical for server and managed data endpoints. Spell a Unix socket by its bytes. Keep default_graph out of the hash, as this digest already does. Extend targets_tests with the four HTTP spellings and the two non-UTF-8 socket paths from #1080.

Gaps named on this PR

Checked against this head, not against an earlier branch.

  1. Typed refusal codes. Partially present. The nine names exist as TargetError string codes and are copied to JSON code when machine output is on (crates/omnigraph-cli/src/app.rs). They are target_unknown, target_invalid, target_exists, target_is_default, config_not_editable, target_kind_unsupported, credential_terminal, credential_anonymous, and credential_missing. They are not ErrorCode variants, they do not use CliRefusal, and the user docs have no code table. That registry is the one feat(server)!: say on every error body whether the request ran #1076 adds, and it is not on this base. This is a real gap against feat(cli): name targets in the operator configuration #1080's machine contract. It can land with feat(server)!: say on every error body whether the request ran #1076. It does not by itself block this PR if the string codes stay stable.

  2. protocols in version --json. Real. This head reports a scalar target_protocol: 1 (crates/omnigraph-cli/src/commands/local/output.rs). feat(cli): name targets in the operator configuration #1080 and RFC rfc: graph access and cross-process writes #1017 use protocols: { target, credential }. The user reference in this PR documents target_protocol, so the docs match the code. Studio's selector will miss the scalar. Pick one spelling before protocol 1 is consumed, and make version --json, the reference, and the skill the same. I would use the object, because feat(cli): say who you are at a target and what you may do #1081, feat(cli): serve a target for you on loopback #1083, and feat(cli): bridge an agent's MCP over stdio to a target #1084 already key on it and will add access, serve, and local_server_record.

  3. Binding digest. Real. This is blocking finding 2.

schema plan on a root plus a selected graph matches the RFC end state. The interim refusal from #1080 does not need to come back.

Optional

  • accepts_actor in planes.rs is an allow-list and it matches the commands fix(cli)!: refuse --as wherever a command records no actor #1059 marks as consuming an actor, including the read commands that used to drop --as. A new subcommand compiles without a classification because the pattern is not exhaustive. An exhaustive match, as in fix(cli)!: refuse --as wherever a command records no actor #1059, fails the build until the new command is classed. Refusal is the safe default today.
  • The second commit reproves a change-feed branch head on a fresh zero-cache session that keeps the captured store registry (crates/omnigraph/src/changes/enumerate.rs). The parent commit de6e0639 passed &store.session(), the data session. That session can still hold an earlier page. The existing owner is change_feed_poll_refuses_table_open_aba_without_etag_witness. It does not assert which session is used, so a cache miss passes on both commits. Add a regression that a warm data-session metadata cache cannot hide a deleted-and-recreated branch head. GQT cannot see the session.
  • identity_recovery.rs raises recursion_limit to 256. Boxing GraphClient moved the large state off the stack, and the limit raise remains. A later command variant can pass that ceiling again.
  • Draft rfc: named targets and CLI coherency #675 still says RFC 0059 adds no target administration group. This PR's RFC adds target list|show|add|remove|import. Close or retarget rfc: named targets and CLI coherency #675 when this text is the accepted one, so two RFC 0059 bodies do not stay open.

Sibling PRs and split

Keep the CLI grammar, import, credentials, docs, skill, and changelog in one PR. A half-migrated flag set is a worse break. Fix the S3 capture and the digest here. They are the substrate the new grammar calls.

PR Alignment
#1059 Same --as allow-list. Rebase will conflict in planes.rs. The exhaustive match is the part to keep.
#1078 Exit statuses are unchanged here. Every TargetError exits 2. Rebase onto the outcome table after #1076.
#1076 Supplies the ErrorCode registry the nine target codes still need.
#1081, #1083, #1084 Built on #1080. They need this target model, protocols, and the canonical digest.
#1075, #1077 Server loopback work. They stay compatible if they compare the same canonical binding digest.
#675 Stale draft of this RFC.

Liability

The resolver is one function with one order. Five more command families can call it without a new flag. That lowers long-term liability, and the large deletion of the old selectors is real evidence of that.

The S3 copy raises liability in the other direction. Five more AmazonS3ConfigKey variants would become named-target behavior with no review. An allow-list stops that. The canonical digest is one identity function shared by credentials, JSON, and later local-server election. A raw-string hash becomes a second identity.

Net line change is about +13,000 / −10,900 across 164 files. The deletion of the old routing paths is the part that removes liability. The new target module is the replacement source of truth, which is appropriate. The captured-option map is the part that adds liability until it is classed.

Validation

  • Head: 84283920f89cc089ae36a3efec72610318bf9634. Base: 9e2425d26a03b1b5628030a359ee51f096d3ca1c. No other review on this head.
  • Code inspection of target resolution, credential scope, import, command applicability, and the pinned Lance 11.0.0 AWS and Azure store providers (with_env_s3, build_aws_credential, with_env_azure).
  • Lance object-store guide: credentials default to the provider chain; static keys and aws_provider_scheme override that chain; region and endpoint may come from the environment or from storage options.
  • Storage test above, on this head. Result: the unclassified keys are captured. The probe was removed. It was not committed.
  • URL folding check with url 2.5.8, as listed under blocking finding 2.
  • I did not re-run the author-reported CLI suite, GQT, or the change-feed failpoint. I did not run live S3 or Azure.

GQT cannot express provider options, CLI JSON, or a Lance session cache. The regression for finding 1 belongs in omnigraph-storage binding tests. The regression for the session fix belongs on the existing change-feed failpoint owner.

ragnorc added a commit to ragnorc/omnigraph that referenced this pull request Oct 20, 2026
… reads

The review of c4641d7 found the engine section did not match the
publisher on main: a row change must record a graph commit, and the
preconditions read only the head and branch identity, so a
head-preserving tombstone or drop record stopped nobody.

- Control facts (tombstone, registration, drop record) change no table
  row and record no commit; check_publish_precondition reads the facts
  that name an attempt on every attempt, for every precondition.
- A create registers on main before it writes its ref, so the
  registration is the visibility point and cleanup reads it instead of
  an age. Until PR 963 lands, a registration refuses when main's
  contract moved past its fork; after it, PR 963's rule wins.
- Only the upgrade census raises the new stamp.
- RFC 0059 (PR ModernRelay#1090) owns addressing and the target and credential
  commands; deployments pass their root through --target.
- The access route is ModernRelay#1073's; this RFC adds the command. A direct
  graph inside a cluster refuses and names the root.
- Storage outcomes are PR 1093's; storage_unavailable goes, and
  disposition.check is a later phase.
@aaltshuler
aaltshuler added this pull request to the merge queue Oct 20, 2026
Merged via the queue into ModernRelay:main with commit 2c9eb1e Oct 20, 2026
32 of 34 checks passed
ragnorc added a commit to ragnorc/omnigraph that referenced this pull request Oct 20, 2026
ModernRelay#1090 landed on main, so the RFC no longer waits on it: blocked_on is
empty, and the Motivation, rollout and Appendix A5 say the target
commands build on main.
ragnorc added a commit to ragnorc/omnigraph that referenced this pull request Oct 20, 2026
Main replaced the legacy routing flags with explicit targets (ModernRelay#1090). The
actor assertion sits on that structure: `GraphClient::from_target` and the
served cluster client send `--as` as `Omnigraph-If-Actor` on a server
target, where ModernRelay#1090 refused it, and only a managed target still refuses
`--as`. `accepts_actor` keeps deciding which commands take it. The HTTP
contract stays 0.14.
ragnorc added a commit to ragnorc/omnigraph that referenced this pull request Oct 20, 2026
It brings main's explicit targets (ModernRelay#1090) and Lance 13. A target refusal
that ModernRelay#1090 reports with the command's evidence carries `disposition`, as
every other data-write failure does.
ragnorc added a commit to ragnorc/omnigraph that referenced this pull request Oct 20, 2026
Brings in main through ModernRelay#1076, including ModernRelay#1090's explicit targets. The
exit table keeps its classification: the removed use and profile
commands leave it, and the target and credential commands, which keep
their own failure reports, join the unclassified ones. ModernRelay#1078's tests
move to --target, ModernRelay#1090's usage-error tests expect exit 64, and the
diagnostics checks pass the destination line ModernRelay#1090 prints first.
ragnorc added a commit to ragnorc/omnigraph that referenced this pull request Oct 21, 2026
* docs(rfc): propose local graph sessions and client access

Draft RFC for issue ModernRelay#980: `omnigraph serve` local sessions with session
records, a thin `omnigraph studio` launcher, `omnigraph mcp` for agents,
and `omnigraph credential` for static tokens. Wider-blast-radius changes
are listed in Appendix A with their filed issues.

* docs(rfc): add installing Studio as a later, signature-gated phase

* docs(rfc): link Studio's release prerequisites and correct their current state

* docs(rfc): reconcile local sessions with main and open PRs, and define the target writer

* docs(rfc): name local servers and settle records, tokens and agent paths

Rename the session to a local server and --session to --via-server.
Move server records from /tmp, which macOS ages out after three days,
to per-user directories resolved from the account, with the machine
they belong to. Never write a token to a terminal, list live local
servers in targets --json, give each agent context one write path,
add platform coverage, and gather every refusal code in one table.

* docs(rfc): redesign graph access around seven rules and fold in cross-process writes

Rewrite the RFC from first principles: name the target, never the path;
correctness in the engine across processes; one set of operations on three
surfaces; one serving concept with explicit audiences, folding the
omnigraph-server binary into omnigraph serve; --as as a declaration or an
assertion; one outcome model and exit table; and introspection through
target list and access. Bring cross-process writer safety and the access
route into scope, with the engine design on the __manifest version CAS,
and land the interfaces before the engine phase. Rename the file to match
the new title.

* docs(rfc): align outcomes, serving lifecycle and late writes with the storage-uncertainty fix

* docs(rfc): elect one local server per destination and close the reuse, handoff and MCP gaps from review

* rfc: align graph access with the phase 1 and phase 3 implementations

The actor header rides the HTTP contract bump to 0.14 instead of a
capability response header, and /mcp compares it after authentication
alone. Rule 6 states the outcome table the server implements, with an
earlier publication marked on the engine's error and outcome.check waiting
for an attempt id. The local embedding API names what the implementation
settled: LocalBinding::local for local roots, ReadWriteUnavailable,
ClusterGraph instead of promoting a graph to its cluster, start_local and
LocalServing::release, and one captured ledger revision per read-only
cluster server.

* rfc: align graph access with the disposition, the If-Actor header and the records' machine id

Phase 1's review renamed the error object and the actor header, and
phase 3's review tightened the records' machine id. The RFC now says
what the implementations do:

- The actor header is Omnigraph-If-Actor, after HTTP's conditional
  If-* headers, since a mismatch is a failed condition (412).
- The error object is `disposition`: `execution` is gone because it
  only repeated `effects`; `effects` gains `partial` for a refused
  step after an earlier publication of the same operation; `action`
  gains `fix` for a request that fails the same way on resend. Each
  code names its own action, and partial effects exit 2.
- A record's machine is 32 lowercase hexadecimal digits that are not
  all zeros. Any other value, systemd's first-boot `uninitialized`
  marker included, refuses rather than falling back to another source.
- Windows records wait for their own pull request: until they check
  the directory's access list and read MachineGuid, they refuse.
- The CLI's MCP bridge bullet lists what the bridge actually changes:
  the graph binding, the readOnlyHint filter and local cancellation.

* rfc: decide branch control through control facts each publish attempt reads

The review of c4641d7 found the engine section did not match the
publisher on main: a row change must record a graph commit, and the
preconditions read only the head and branch identity, so a
head-preserving tombstone or drop record stopped nobody.

- Control facts (tombstone, registration, drop record) change no table
  row and record no commit; check_publish_precondition reads the facts
  that name an attempt on every attempt, for every precondition.
- A create registers on main before it writes its ref, so the
  registration is the visibility point and cleanup reads it instead of
  an age. Until PR 963 lands, a registration refuses when main's
  contract moved past its fork; after it, PR 963's rule wins.
- Only the upgrade census raises the new stamp.
- RFC 0059 (PR ModernRelay#1090) owns addressing and the target and credential
  commands; deployments pass their root through --target.
- The access route is ModernRelay#1073's; this RFC adds the command. A direct
  graph inside a cluster refuses and names the root.
- Storage outcomes are PR 1093's; storage_unavailable goes, and
  disposition.check is a later phase.

* docs(rfc): discontinue the second serving model

* docs(rfc): record MCP bridge closure and defer selective reuse

* rfc: treat RFC 0059's implementation as merged

ModernRelay#1090 landed on main, so the RFC no longer waits on it: blocked_on is
empty, and the Motivation, rollout and Appendix A5 say the target
commands build on main.

* rfc: accept graph access and cross-process writes

Maintainer decision: the actor assertion, the error-code registry and
disposition, the exit table, the access command, operation parity, the
existing-server MCP bridge and Studio opener, and the engine control-fact
design with its qualification gates. Appendix A stays separate decisions.

* rfc: give every control fact its attempt id and gate the upgrade on registrations

The review of eeb6e12 found two holes in the engine section:

- A control fact records no graph commit, so the head-equality read-back
  cannot tell two facts apart after a lost acknowledgement, and the
  owner's own retry met its refusal. Each control-fact operation now mints
  one attempt id that every fact it writes records: the read-back compares
  it, a pending control fact is keyed by it, and a retry treats its own
  fact as landed. Deletes and drops converge.
- System-column upgrade pins main's head, not its version, so a
  registration did not stop it. Its attempts now read main's
  registrations every attempt, until PR 963.

Cleanup's registration rule now covers refs as well as trees, under the
collector's dependency closure; a create no longer completes a crashed
create's registration; the pending-branch service_unavailable covers one
branch; branch list shows a registered branch without a ref as not ready;
the --as help quote is current.

* rfc: name the access command's test owner and target terms

* rfc: settle a control fact from the fact, and keep the collector's keep set

The review of ef44175 recommended merging, with four optional
corrections: read-back has three results; a caller settles a control
fact from the fact, since the head does not move; cleanup candidates
still pass protected_manifest_branches and retained_merge_bases; a crash
loses the attempt id, so only delete and drop converge after one. A
not-ready branch's listing fields come from its registration.

* rfc: fence an unknown control fact by its version key

Storage outcomes per operation dropped its pending-publication registry:
an unknown publication is recorded nowhere and blocks nothing, and its
version key fences it. A control fact follows the same fence, and the
one-branch service_unavailable row goes. Read-back follows ModernRelay#1092's
split, a not-ready branch's absent listing fields are named, and the
access evidence uses RFC 0059's target kinds.

* rfc: align the access view field and disposition.check with actor views

* rfc: settle a control fact when its attempted version is readable

---------

Co-authored-by: aaltshuler <andrew@collectivelab.io>
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.

2 participants