Repository navigation
Carry opaque registry extensions through DatabaseInfo and drop the tray's synced label - #3399
Conversation
Code Review SummaryReview Type: Initial Review (no prior reviews; head Small, well-scoped additive change. I traced the serde/toml behaviour, every registry mutation path, the proto/DTO/frontend plumbing, the tray doc against Requirements Check (issue #3341)
Verification of the areas called out
Code Review FindingsCritical: none. Important: none. Suggestion (non-blocking, for the follow-up that adds
|
mstomar125
left a comment
There was a problem hiding this comment.
Automated pragmatic-code-review: APPROVE (posted as a comment, GitHub blocks self-review states). Full findings in the review comment above.
Address-review summaryReviewed: the pragmatic review of head Addressed: 0. Skipped: 1, deferred to the issue that owns it.
No code changed, no commits, no push. Head stays Re-Review DecisionDecision: NO RE-REVIEW NEEDED Rationale: the review raised no defect and nothing was changed after it. The head the reviewer saw is the head the PR still has. |
…ay's synced label DatabaseEntry.extensions holds every key of a databases.toml entry that the registry does not define, verbatim through load and save (serde flatten into a toml::Table); an unknown key used to be ignored on load and dropped on the next save. DatabaseInfo.extensions (proto field 10) carries the string-valued entries; the desktop DTO and the frontend DatabaseInfo type pass them through. Core reads no key from the map. The tray's database submenu no longer labels a database "synced", and its doc now describes what it renders: the default flag, the live open state and the missing-file state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
e3d6902 to
517fc6c
Compare
Closes #3341
Carries an opaque, per-database
extensionsmap end to end (ADR-083 §2, decision 2-A) and deletes the tray's "synced" label (ADR-083 §2 and §7 item 2). Part of the Pro/core boundary epic (#3298). Core reads no key fromextensions. Nothing is removed yet: proto fields 8 and 9 and the typed binding fields stay until #3342.What changed
packages/daemon/src/services/database_manager.rs):DatabaseEntry.extensions: toml::Tablevia#[serde(flatten)]. Every key of adatabases.tomlentry that the registry does not define now loads into it and is written back on every save. Before, an unknown key was ignored on load and silently dropped on the next save. The threeOptionfields gainedskip_serializing_if = "Option::is_none".database_service.proto):map<string, string> extensions = 10onDatabaseInfo.listing_to_infofills it from the string-valued entries and leaves other value types (integer, boolean, array, table) in the registry, out of the response.packages/desktop-app/app-lib/src/commands/database.rs, the crate split has landed):DatabaseEntry.extensions: BTreeMap<String, String>, copied into_entry.DatabaseInfo.extensions: Record<string, string>,extensions: {}onIMPLICIT_BROWSER_DATABASE, and on the four fixtures that build a fullDatabaseInfo.syncedmarker is gone and thedatabase_menu_entriesdoc is rewritten to match what it renders (default flag, live open state, missing-file state; the old "deliberately NOT whether open" paragraph was stale).Existing registries stay readable
A registry written before this change may carry the typed binding fields. They still load into their typed fields (the fields are untouched) and are not duplicated into
extensions; the manual check below covers a copy seeded with them.Tests
database_manager:registry_round_trips_entry_keys_it_does_not_define(string, nested table sorted before a scalar, native TOML datetime; defined keys are intact; save and reload keep everything; a second save writes the same bytes) anda_rename_keeps_extension_keys. The existing reload test also asserts a typed-field entry loads with emptyextensions.database_service:listing_to_info_carries_string_extensions_only.app-libcommands::database:to_entry_passes_extensions_through, including the camelCase JSON key.tray:labels_carry_default_state(renamed),markers_render_in_a_stable_ordernow expectsAll — default · open,extension_keys_add_no_marker, anda_recorded_binding_adds_no_marker(an absence test, so its key is built from fragments) which guards the deleted label now that no fixture binds a database.Mutation checks (each reverted afterwards):
#[serde(flatten)]->#[serde(skip)](today's behaviour)registry_round_trips_entry_keys_it_does_not_define,a_rename_keeps_extension_keys,listing_to_info_carries_string_extensions_onlyextensionsextension_keys_add_no_markersyncedmarker restoreda_recorded_binding_adds_no_markerlisting_to_infostringifies every valuelisting_to_info_carries_string_extensions_onlyto_entrydropsextensionsto_entry_passes_extensions_throughskip_serializing_iffrom the threeOptionfieldsNonein a flattened map either way, so no test can tell. Kept because the issue specifies it and it stops the save depending on that serializer detail.Manual check (isolated
NODESPACE_HOME, never~/.nodespace)A
databases.tomlseeded with the old typed binding fields, extra scalar keys, an integer key and a nested table, on two entries. A headlessnodespacedfrom this branch started and listed both databases (nodespace database list). Over the socket,DatabaseService.Listreturned the typed binding fields in their own fields andextensionsholding only the string keys ({"plugin_state":"keep"},{"plugin_label":"blue"}); the integer and the table stayed out. Afternodespace database renameon both entries, the file still held every key (typed fields,plugin_count,plugin_state,[databases.extra]), with the values unchanged. On the first save, extension keys are written after the typed ones in key order and arrays are laid out by the pretty serializer.Ratchet
bun run scripts/check-pro-boundary.tsexits 0.BASELINESis not touched, per the standing decision (parallel PRs collide on those lines; the final issue tightens them), so the issue's step 3 is not applied. Counts against the ceilings:cloudBindState203 -> 202 andtenantWording463 -> 453; no count rose.Deviations from the issue
app-lib/src/commands/database.rsafter the crate split.BASELINESleft alone (above).a_recorded_binding_adds_no_marker(above), so deleting the label is guarded by something that fails if it returns.info_to_jsonis unchanged: it never printed the binding fields and the issue does not ask forextensionsthere.🤖 Generated with Claude Code