feat(rest/protocol): extend droppedFields write-observability to bulk paths + client SDK (#3455)#3468
Open
os-zhuang wants to merge 3 commits into
Open
feat(rest/protocol): extend droppedFields write-observability to bulk paths + client SDK (#3455)#3468os-zhuang wants to merge 3 commits into
os-zhuang wants to merge 3 commits into
Conversation
… paths + client SDK (#3455) Follow-up to #3448 (#3431 D2). Single-write PATCH/POST /data already surfaces LEGALLY-stripped write fields (readonly #2948 / readonlyWhen #3042 / #3043 create ingress) as `droppedFields`; the bulk paths dropped them silently. This closes out the deferred波及面. - metadata-protocol: updateManyData + batchData collect per-row onFieldsDropped and attach to each result row; insertManyData attaches per-row via ingress diff; createManyData returns an aggregated top-level droppedFields (no per-row slot; static-readonly strip is schema-uniform). Correctness fix: updateManyData and batchData never threaded the caller `context` — bulk writes ran context-less (RLS/FLS/readonlyWhen without the principal; batch create strip forced non-system). All engine calls now run under the resolved context. - spec: BatchOperationResultSchema gains optional per-row droppedFields (covers updateMany + batch); CreateManyDataResponseSchema gains the aggregated one. Both omit-when-empty. No X-ObjectStack-Dropped-Fields header for batches by design — one header cannot express per-row drops, so the body is the canonical channel. - client: CreateDataResult / UpdateDataResult gain droppedFields?: DroppedFieldsEvent[]. - hono adapter + plugin-hono-server: x-objectstack-dropped-fields added to the default Access-Control-Expose-Headers (lockstep across both CORS sites). - Design decision: kept precise droppedFields (reused DroppedFieldsEventSchema) over a generic warnings envelope, for symmetry with the shipped single-write path. - GraphQL item is a no-op: GraphQL has no runtime (kernel.graphql unassigned, handleGraphQL 501s, discovery never advertises it) — nothing to wire until an engine lands, at which point the protocol-layer droppedFields is already present. Tests: 10 bulk protocol cases (per-row + aggregated + context threading + returnRecords=false) and a CORS default-expose assertion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 5 package(s): 108 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…3455) Generated from the batch/protocol Zod schemas — BatchOperationResult (per-row) and CreateManyDataResponse (aggregated) gained droppedFields. Regenerated via gen:schema && gen:docs; these files are generated, not hand-edited. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…elds transitive deps (#3455) batch.zod.ts now imports DroppedFieldsEventSchema from data-engine.zod, whose transitive imports (kernel/execution-context, security/explain) pull those into the objectstack-api skill's referenced-schema set. Regenerated via gen:skill-refs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3455. Follow-up to #3448 (#3431 D2 波及面): single-write PATCH/POST
/dataalready surfaces LEGALLY-stripped write fields (readonly#2948 /readonlyWhen#3042 / #3043 create ingress) asdroppedFields; the bulk paths dropped them silently and the typed client warning + CORS mirror were deferred. This closes those out.What changed
Bulk passthrough —
@objectstack/metadata-protocolupdateManyDataandbatchData(update/upsert rows): register a per-rowonFieldsDroppedcollector, attach events to that row's result.insertManyData: per-rowdroppedFieldson each outcome (ingress diff, 1:1 with rows).createManyData: aggregated top-leveldroppedFields(one event per object/reason, union of field names) — its{ records, count }response has no per-row slot, and the insert-time strip is static-readonlyonly (schema-uniform), so aggregation is faithful, not lossy.updateManyDataandbatchDatanever threaded the caller's executioncontext— bulk writes ran context-less, so RLS/FLS andreadonlyWhenevaluated without the caller's principal, and the batch create-ingress strip was hard-coded to a non-system context. All engine calls in both methods now run under the resolvedcontext.Contract —
@objectstack/specBatchOperationResultSchemagains optional per-rowdroppedFields(coversupdateMany+batch, which aliasBatchUpdateResponseSchema).CreateManyDataResponseSchemagains the optional aggregateddroppedFields.X-ObjectStack-Dropped-Fieldsheader for batches by design: one response header cannot express per-row drops, so the per-row body field is the canonical bulk channel.Typed client —
@objectstack/clientCreateDataResult/UpdateDataResultgaindroppedFields?: DroppedFieldsEvent[].CORS —
@objectstack/hono+@objectstack/plugin-hono-serverx-objectstack-dropped-fieldsadded to the defaultAccess-Control-Expose-Headers(lockstep across both Hono CORS sites) so a cross-origin browser can read the single-write drop header. The bodydroppedFieldsremains the primary, cross-origin-safe surface.Design decisions
droppedFields(reusedDroppedFieldsEventSchema) over a genericwarningsenvelope, for symmetry with the already-shipped single-write path. A generic envelope, if wanted later, should migrate single + bulk together.kernel.graphqlis unassigned everywhere,handleGraphQLreturns501, and discovery never advertises/graphql. There is no schema generator or mutation resolver to expose a typed payload field on — nothing to wire until a GraphQL engine lands, at which point the protocol-layerdroppedFieldsis already present and only the GraphQL schema projection would remain.Tests
packages/metadata-protocol/src/protocol.dropped-fields.bulk.test.ts— 10 cases: per-row (updateMany / batch / insertMany), aggregated (createMany), context-threading assertions, system-context exemption,returnRecords:falsepreservesdroppedFields.packages/adapters/hono/src/hono.test.ts— default expose-header assertion for the new header.🤖 Generated with Claude Code