Skip to content

Core sync: POST /types must go through the invariant layer — defineType + drift guard, not adapter.saveType (core #68) #40

Description

@cuibonobo

Server side of haverstack/core#68, and the server's clearest instance of the review's layering principle (adapters are storage engines; Stack is the invariant layer).

Problem

POST /types writes directly to the adapter (src/routes/types.ts:53):

await adapter.saveType(type);

saveType is INSERT OR REPLACE — so the wire inherits exactly the silent-replace hole core #68 describes: re-POST com.example/note@1 with a different shape and every existing record of that type is silently mislabeled. The route validates the submitted hash matches the submitted schema (types.ts:38-40, from #15), which proves internal consistency of the request but compares against nothing stored — the one comparison schemaHash exists for.

The route also constructs the StackType by hand (id/baseId/version/name/createdAt), duplicating in the HTTP layer what defineType() owns, and accepts a client-supplied createdAt — which core #68's flow makes moot (no-op and additive paths preserve the stored createdAt).

Decided direction (upstream)

Core #68 item 5 says it directly: "Server-side POST /types runs the same check… saveType() stays a dumb REPLACE — legality is decided in the invariant layer."

Work items

  • Route through Stack.defineType() once the drift-guard flow lands (blocked on core #68); delete the hand-rolled StackType construction
  • Rethink the request shape: with the server computing the hash and defineType deriving baseId/version from the id, the client-supplied schemaHash/baseId/version/createdAt fields become either redundant or 400-checked consistency inputs — decide with the spec update
  • Keep requireOwner (type registration is owner surface today; grants don't cover it)
  • Tests + conformance fixtures (Core sync: adopt the shared conformance fixtures; fix the PATCH body shape; add the intent-split endpoints (core #52) #32): re-POST matrix — identical → no-op (no createdAt churn), additive → accepted, illegal → 409 schema_drift

Refs haverstack/core#68, haverstack/core#47 (additive policy), haverstack/core#53, #32, #33.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions