docs: bless staging whole-object create + delete (edit/create/delete in one review + save) - #16
Conversation
client-state-model.md and saving.md covered edit+save but said nothing about whole-object create/delete, so the next consumer re-derives (or mis-derives) it. The store keys on metadata.uid and has no merge for a create or a delete — that is correct and read-only by design — so staging the pending intent is the consumer's job. Document the pattern once: page-local pendingCreates/pendingDeletes aggregated with changes() into one review list under one Save, and the two optimistic primitives (adoptSaved / removeResource) that reflect the result before the watch echoes it, both idempotent with the echo. Two caveats the pattern needs and nobody states: a create can only be reflected after the server assigns the uid (never fabricate one), and an optimistic delete is not self-healing because a failed delete produces no watch event. Refs #15. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The docs now bless adoptSaved as the optimistic-create primitive and lean on its I-IDEMPOTENT contract: an optimistic insert and the watch echo of the same create must converge to one object, keyed by uid, not two cards. Nothing pinned that. (The delete/recreate identity half already is, by delete-recreate-uid.) Teach the client loader an `adopt` edit op — it delivers the object a save returned via store.adoptSaved, carrying a bodies/ ref rather than a uid/path, since it is a delivery, not an edit. The two edit invariants (addresses-a-delivered-uid, has-a-path) skip it for that reason. The gateway suite is untouched: it treats `client` as opaque, and the fixture has no watch. Refs #15. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThe changes document host-side create/delete staging and add conformance support for an ChangesCreate adoption and host state guidance
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
docs/client-state-model.md (1)
74-75: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winDistinguish the local draft key from
metadata.uid.The example says creates are id-less but includes
id, which is ambiguous beside the UID-based store identity. Rename it todraftIdor explicitly state that it is a client-only key and must never be used as the resource UID.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/client-state-model.md` around lines 74 - 75, Update the pendingCreates example to use draftId instead of id, and clarify that this is a client-only key distinct from metadata.uid and must never be used as the resource UID.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/client-state-model.md`:
- Around line 90-92: Update the save flow described by adoptSaved and
removeResource to clear the corresponding entries from pendingCreates and
pendingDeletes after successful create and delete operations. Ensure completed
mutations are removed from the page-local pending lists so they cannot remain in
the review list or be submitted again.
- Around line 62-66: Update the store ownership description near `adoptSaved` to
state that it holds server-identified objects, including projected objects
adopted before their watch echo arrives, rather than only objects delivered by
the stream. Preserve the explanation that pending creates lack a server uid and
therefore are not stored.
In `@docs/saving.md`:
- Around line 121-122: Update the documented client/server flow around the 204
response so the server handler only returns http.StatusNoContent, while the
browser consumer calls store.removeResource(uid) after a successful response
using its tracked UID. Remove the server-side optimistic-removal implication and
preserve the existing deleted-event behavior.
- Around line 97-100: Update the example flow around readObject and the dynamic
client Create call to validate and sanitize the browser-supplied object first.
Enforce the expected GVK, authorized scope and name, and permitted fields, then
pass only the sanitized object to Create; do not rely on Kubernetes admission as
the host-side validation step.
In `@packages/krm-stream/test/conformance.ts`:
- Around line 29-37: The FixtureEdit type in
packages/krm-stream/test/conformance.ts (lines 29-37) must use discriminated
variants: require body and omit uid/path for adopt, while requiring uid/path for
all other operations. In packages/krm-stream/test/expect.ts (lines 27-33),
update the adopt handling to pass e.body directly to body() without a non-null
assertion.
---
Nitpick comments:
In `@docs/client-state-model.md`:
- Around line 74-75: Update the pendingCreates example to use draftId instead of
id, and clarify that this is a client-only key distinct from metadata.uid and
must never be used as the resource UID.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1570b7bf-88c5-426b-8696-29d4fab175ce
⛔ Files ignored due to path filters (2)
conformance/gen/bodies.jsonis excluded by!**/gen/**conformance/gen/fixtures.jsonis excluded by!**/gen/**
📒 Files selected for processing (8)
conformance/README.mdconformance/bodies/cm-created.v1.yamlconformance/fixtures/adopt-created-dedup.yamldocs/client-state-model.mddocs/saving.mdpackages/krm-stream/test/conformance.test.tspackages/krm-stream/test/conformance.tspackages/krm-stream/test/expect.ts
- Frame store ownership as "has a server identity (uid)", not "the stream delivered it": adoptSaved inserts a save response before its echo, so the stream-only phrasing was too absolute. - Note that a successful write must clear the page-local pendingCreates/ pendingDeletes entry — the store primitives touch the store, not those lists, so a completed mutation left staged can be submitted twice. - Show host-side create validation inline (validateCreate) and stop listing API-server admission as a host-side check — it is defense in depth behind the write, not a substitute for validating before it. - Rename the pendingCreates key id -> draftId and call it a client-only key, distinct from metadata.uid. - Attribute removeResource to the browser in the delete handler comment, not the server handler. Refs #15. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks @coderabbitai — addressed in b14707e. Dispositions: Fixed (4):
Declined (1):
|
|
Tip For best results, initiate chat on the files or code changes.
On the declined item: agreed, keeping the single Nice work tightening this up. ʘ‿ʘ ✏️ Learnings added
|
Closes #15 (the documentation ask). Leaves the optional
PendingMutationshelper out of scope on purpose — see below.What and why
The console this library was extracted from grew whole-object create and delete and wanted them in the same review-and-save pane as field edits.
LiveResourceStoreis deliberately not the home for create/delete: it keys onmetadata.uid(a pending create has none) and its value is the three-way merge (a create has nothing to merge, a delete nothing to reconcile). That read-only stance is correct — what was missing was guidance, so the next consumer doesn't re-derive it.Commits
docs — a "Creating and deleting whole objects" section in
client-state-model.mdand create/delete siblings of the save handler insaving.md. Both point atadoptSaved/removeResourcefor reflecting the result before the watch echoes it, and both keep the 204-and-let-the-echo-settle-it recommendation. Two caveats the pattern needs and nobody had written down:conformance — a new
adopt-created-dedupfixture pins theI-IDEMPOTENTcontract the docs now lean on: an optimisticadoptSavedand the watch echo of the same create converge to one object by uid, not two. The client loader learns anadoptop (it delivers a save response rather than editing a delivered object, so it carries abody, not auid/path; the two edit invariants skip it for that reason). The gateway suite is untouched — it treatsclientas opaque and the fixture has nowatch. The delete/recreate identity half was already pinned bydelete-recreate-uid.Deliberately out of scope
The issue's open question — a thin
PendingMutationsaggregator (edits + creates + deletes → one submit set). Declined for core, for a sharper reason than "reads only": the store holds only objects the stream delivered, and the one knowledge-laden part of aggregation (dedup an optimistic create/delete against its echo by uid) already lives in the store viaI-IDEMPOTENT. What's left is knowledge-free page-local bookkeeping with a single known consumer. If a second consumer wants it, it's a natural fit for a write-side companion rather than this read library.Verification
task lint,task test, andtask fixtures-checkall green.Summary by CodeRabbit
Documentation
Bug Fixes
uid.Tests
adoptedit operation and its expected shape.