Skip to content

feat: drop_named_graph + fluree graph CLI (list, drop)#1247

Open
bplatz wants to merge 4 commits into
mainfrom
feature/drop-branch
Open

feat: drop_named_graph + fluree graph CLI (list, drop)#1247
bplatz wants to merge 4 commits into
mainfrom
feature/drop-branch

Conversation

@bplatz
Copy link
Copy Markdown
Contributor

@bplatz bplatz commented May 19, 2026

Summary

  • Adds a per-branch named-graph drop: Fluree::drop_named_graph(ledger_id, graph_iri) retracts every triple currently asserted under a named graph in a single new commit. History at older t is preserved, the graph IRI keeps its g_id, and the operation is idempotent on an empty graph (no commit produced).
  • Wires up a wire endpoint POST /v1/fluree/drop-graph (admin-protected) and a matching CLI: fluree graph drop <iri> plus a companion fluree graph list. Both subcommands support --remote, tracked-remote auto-routing, and --direct.
  • Fixes the ledger.named-graphs block in the /info payload so newly registered graphs show up immediately (not after the next index build).
  • Fixes fluree branch drop so a second drop of an already-retracted branch prints "no-op" instead of "Dropped branch".

Details

drop_named_graph (new)

Fluree::drop_named_graph(ledger_id, graph_iri) -> Result<DropNamedGraphReport> walks the live triples under graph_iri and stages a single retract-only commit. Concrete behavior:

  • History preserved. Time-travel reads at any prior t see the old graph contents. The graph IRI keeps its assigned g_id; later inserts re-populate it normally.
  • Per-branch. Dropping on mydb:dev leaves mydb:main untouched.
  • Idempotent. An already-empty graph short-circuits with no commit produced and a DropStatus::AlreadyRetracted outcome.
  • System graphs rejected. urn:fluree:default, urn:fluree:txn-meta, urn:fluree:config (the three system graphs) return ApiError::Http(400). Unknown IRIs return 404 before staging so the graph registry isn't silently extended.
  • IRI validation. graph_iri is validated as an absolute IRI: requires a <scheme>:<rest> head, no whitespace, no C0/DEL control characters, and rejects RFC 3987-excluded characters. Leading/trailing whitespace is rejected outright, not silently trimmed (7 unit tests in validate_absolute_iri).

Wire endpoint: POST /v1/fluree/drop-graph

Admin-protected — same bracket as /drop, /create, /reindex. Body and response specified in docs/api/endpoints.md; full server-side contract documented in docs/cli/server-integration.md ("Drop Named Graph Contract").

CLI

fluree graph drop <iri>

fluree graph drop <IRI> [--ledger <name>] [--remote <name>] [--direct]

Three-mode dispatch matching the rest of the --remote family: explicit --remote <name> → named remote; otherwise auto-route through a locally running fluree server start if server.meta.json is present; otherwise direct local execution. --direct skips auto-routing.

fluree graph list

fluree graph list [--ledger <name>] [--include-system] [--json] [--remote <name>] [--direct]

Parses the existing /info payload's ledger.named-graphs section. By default hides the three system graphs; --include-system shows them.

Companion fixes

ledger.named-graphs now built from the live registry

build_ledger_block used to enumerate named graphs via BinaryIndexStore::graph_entries(). Two failure modes:

  • A ledger with no index ever built reported only urn:default.
  • A graph registered in a commit after the last index build was silently missing from info.ledger.named-graphs until the next index ran.

Since fluree graph list parses that same payload, the bug surfaced there as well — newly registered user graphs wouldn't show up between drops or right after an insert.

Fixed by iterating ledger.snapshot.graph_registry.iter_entries() instead, which is mutated at commit-apply time and so is always current. Per-graph flakes / size totals still come from IndexStats.graphs when populated and fall back to 0 otherwise.

fluree branch drop honors DropStatus::AlreadyRetracted

Both the local and remote branch-drop paths in fluree-db-cli/src/commands/branch.rs were only inspecting the deferred field when deciding what to print, so a second drop of an already-retracted branch was reported as a successful "Dropped branch" instead of a no-op. The bug applied to the local report and to the JSON response handler (print_branch_dropped).

Both paths now branch on the authoritative status / DropStatus field:

Status Output
AlreadyRetracted "Branch '<name>' was already retracted (no-op)."
NotFound "Branch '<name>' not found."
Dropped Existing dropped / deferred-retract messages, keyed on deferred.

Docs

  • New: docs/cli/graph.md — full reference for the fluree graph subcommand family.
  • New: "Drop Named Graph Contract" and "Graph List Contract" sections in docs/cli/server-integration.md.
  • New: POST /drop-graph spec in docs/api/endpoints.md.
  • Cross-links: docs/cli/drop.md and docs/concepts/datasets-and-named-graphs.md point at the new graph reference.
  • Updated: docs/SUMMARY.md, docs/cli/README.md table of contents.
  • Updated: /info contract entry in server-integration.md now notes ledger.named-graphs as required for fluree graph list.

Tests

  • 11 integration tests in fluree-db-api/tests/it_drop_named_graph.rs covering:
    • Happy path single-graph drop, multi-triple graph drop.
    • Idempotency on an already-empty graph (no commit produced).
    • History preservation via DatasetSpec + TimeSpec lookups at older t.
    • Per-branch isolation: drop on one branch leaves the other intact.
    • Every validation / rejection branch (system graphs, unknown IRI, whitespace, invalid scheme, control characters, RFC 3987 excluded chars).
  • 7 unit tests for validate_absolute_iri.
  • it_ledger_info_named_graphs.rs (179 lines) covers the /info registry fix — pre-index, post-insert, post-drop snapshots all agree with the live registry.
  • Existing it_branch extended with assertions for the AlreadyRetracted CLI output fix.

bplatz added 3 commits May 17, 2026 18:35
`Fluree::drop_named_graph(ledger_id, graph_iri)` retracts every triple
currently asserted under a named graph in one new commit. History at
older `t` is preserved, the graph IRI keeps its `g_id`, drops are
per-branch. System graphs (default, txn-meta, config) are rejected;
unknown IRIs return 404 before staging so the registry isn't silently
extended. Idempotent on an already-empty graph (no commit produced).

Wire endpoint: POST /v1/fluree/drop-graph (admin-protected). CLI:
`fluree graph drop <iri> [--ledger] [--remote]` plus a companion
`fluree graph list [--include-system] [--json]` that parses the
existing `/info` payload's `named-graphs` section. Both subcommands
support `--remote`, tracked-remote auto-routing, and `--direct`.

`graph_iri` is validated as an absolute IRI: `<scheme>:<rest>` head,
no whitespace, no C0/DEL controls, no RFC 3987-excluded characters.
Leading/trailing whitespace is rejected, not silently trimmed.

Docs: new docs/cli/graph.md; Drop Named Graph Contract and Graph List
Contract in docs/cli/server-integration.md; POST /drop-graph spec in
docs/api/endpoints.md; cross-links from docs/cli/drop.md and
docs/concepts/datasets-and-named-graphs.md; SUMMARY and cli/README
updated. /info contract now notes `ledger.named-graphs` as required
for `fluree graph list`.

11 integration tests in it_drop_named_graph.rs cover the happy path,
idempotency, history preservation via DatasetSpec + TimeSpec, per-
branch isolation, and every validation/rejection branch; 7 unit tests
cover `validate_absolute_iri`.
`build_ledger_block` was enumerating named graphs by iterating
`BinaryIndexStore::graph_entries()`. That meant ledgers with no
index reported only `urn:default`, and any graph registered in a
commit after the last index build was silently missing from
`info.ledger.named-graphs` until the next index. Since
`fluree graph list` parses that same payload, the bug surfaced
there as well — newly registered user graphs wouldn't appear
between drops or after a fresh insert until the indexer caught up.

Iterate `ledger.snapshot.graph_registry.iter_entries()` instead.
The registry is mutated at commit-apply time, so it is always
current. Per-graph `flakes` / `size` totals still come from
`IndexStats.graphs` when populated and fall back to `0` otherwise.

`store: Option<&BinaryIndexStore>` is no longer needed in
`build_ledger_block` and was dropped from the signature.

Regression tests in `it_ledger_info_named_graphs.rs`:
- `named_graphs_visible_without_an_index` — two user graphs seeded
  with no index built; all four (default + two users + txn-meta +
  config) must appear.
- `named_graphs_include_post_index_registrations` — alpha seeded
  and indexed, beta seeded post-index without rebuilding; both
  user graphs must appear.
Both the local and remote branch-drop paths in
`fluree-db-cli/src/commands/branch.rs` only inspected the `deferred`
field when deciding what to print, so a second drop of an
already-retracted branch was reported as a successful "Dropped
branch" instead of a no-op. The bug applied to the local report and
to the JSON response (`print_branch_dropped`).

Both paths now branch on the authoritative `status` /
`DropStatus` field:

- `AlreadyRetracted` -> "Branch '...' was already retracted (no-op)."
- `NotFound`         -> "Branch '...' not found."
- `Dropped`          -> existing dropped / deferred-retract messages,
                        keyed on `deferred`.

Extracted `format_drop_branch_headline` from `print_branch_dropped`
so the status / deferred branching is exercised by six unit tests
in `commands::branch::tests`, including a regression test that
asserts `status: "already_retracted"` wins over a stale
`deferred: true` field.

Locked the underlying API contract in `it_branch.rs` with
`drop_branch_is_idempotent_already_retracted`: a deferred drop on
a branch with children leaves the nameservice record retracted,
and a second `Fluree::drop_branch` call on the same branch must
return `DropStatus::AlreadyRetracted`.
@bplatz bplatz requested review from aaj3f and zonotope May 19, 2026 18:38
@bplatz bplatz changed the title feat: drop_ledger + drop_named_graph + structural root-branch checks feat: drop_named_graph + fluree graph CLI (list, drop) May 19, 2026
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