Skip to content

Commit 8a5f4f0

Browse files
dmealingclaude
andcommitted
docs(#203): implementation plan for @autoset CRUD stamping (cross-port)
Scopes #203: TS already stamps @autoset via Zod transforms; C#/Java/Python/Kotlin generated CRUD do not (Python treats it as DB-default-filled, the others ignore it). The owner contract (insert stamps both; update skips onCreate; patch stamps before the block; insertPreserving escape hatch) + the per-port state + the missing shared gate. Per-port report-only implementation, then a coordinated cross-port api-contract gate + review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGQ7oSuNcjhsMHWwZzhBwr
1 parent 1b3dca6 commit 8a5f4f0

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Issue #203 — Generated CRUD honors `field.timestamp @autoSet: onCreate|onUpdate` (cross-port)
2+
3+
**Goal:** the generated insert/update/patch stamps `now()` for `@autoSet` timestamp columns, so adopters stop hand-writing `now()` in every repository (~32/62 hand-written repos in one adopter traced to this). `@autoSet` is already a registered attr (`FIELD_ATTR_AUTO_SET`, values `onCreate`/`onUpdate`); the gap is **codegen stamping**.
4+
5+
## Owner contract (from the issue — the spec)
6+
- **insert** stamps EVERY `onCreate` AND `onUpdate` column with `now()` — the model's value is ignored (a fresh row's `updated_at` == its `created_at`).
7+
- **update(model)** stamps `onUpdate` columns with `now()` and **skips `onCreate` entirely** (never rewrites `created_at` — omitting this is the latent lost-update bug).
8+
- **patch(id){…}** stamps `onUpdate` BEFORE the caller's partial block (a partial update still bumps `updated_at`).
9+
- **insertPreserving(model)** — escape hatch writing the `@autoSet` columns verbatim (import/restore/replication). Emitted ONLY for entities that declare `@autoSet` fields.
10+
- `now()` keyed off the COLUMN's temporal type (generalizes beyond Instant).
11+
12+
## Current per-port state (verified 2026-07-16)
13+
- **TS** — DONE via Zod transforms (`zod-validators.ts`): InsertSchema stamps onCreate+onUpdate (`.optional().transform(() => now())`); UpdateSchema omits onCreate, stamps onUpdate. GAP: only `insertPreserving`.
14+
- **Python** — treats `@autoSet` as DB-server-default-filled (optional wire, `entity_model.py`); NO runtime onUpdate stamping. GAP.
15+
- **C# / Java / Kotlin** — no `@autoSet` timestamp stamping in generated CRUD. GAP. (Kotlin's `onUpdate` refs are relationship referential-actions, not `@autoSet`.)
16+
17+
## No existing cross-port gate
18+
The api-contract corpus's `createdAt` is `@required` + caller-supplied — it does NOT gate `@autoSet` stamping. A new gate is needed.
19+
20+
## Plan
21+
1. **Per-port implementation (report-only agents; C#/Java/Python/Kotlin):** each finds its runtime CRUD (repository/ObjectManager insert/update/patch generator) and stamps per the contract + `insertPreserving`, with PER-PORT tests proving: insert→both stamped==now(); update→updatedAt bumped, createdAt unchanged; patch→updatedAt bumped; insertPreserving→verbatim.
22+
2. **TS escape hatch:** add `insertPreserving` (verbatim, skip the autoSet transforms) for entities with `@autoSet` fields.
23+
3. **Shared cross-port gate (I add last, coordinated):** a dedicated `@autoSet` entity + api-contract scenarios (POST stamps created_at==updated_at; PATCH bumps updated_at, leaves created_at) that ALL ports' generated-artifact lanes pass — the parity lock (like #195's coordinated registration).
24+
4. **Cross-port review** for stamping divergence (does every port skip onCreate on update? stamp onUpdate on patch?).
25+
26+
## Discipline
27+
Report-only agents (NEVER `fork` — see [[fork-subagents-go-rogue-use-general-purpose]]); I verify each gate + review + commit per port. Commit to main (forward-only). Named constants (`FIELD_ATTR_AUTO_SET`, `AUTO_SET_ON_CREATE/ON_UPDATE`). Not a release (bundled with #195/#204/#205 per owner).

0 commit comments

Comments
 (0)