docs(09-05): complete schema-projected CRUD plan
This commit is contained in:
@@ -375,7 +375,7 @@ Plans:
|
|||||||
4. The relation-manager schema supports search/link/unlink/manage-or-view lists for Collections' editors tab, replacing the `partial` field entirely.
|
4. The relation-manager schema supports search/link/unlink/manage-or-view lists for Collections' editors tab, replacing the `partial` field entirely.
|
||||||
5. Admin CRUD endpoints expose `listExtendQuery`/`formExtendQuery`/`formBeforeCreate`/`formBeforeUpdate`/`relationExtendManageQuery` hooks, bulk delete runs each record's lifecycle hooks, and the Settings model binds to a settings screen through the same schema pipeline.
|
5. Admin CRUD endpoints expose `listExtendQuery`/`formExtendQuery`/`formBeforeCreate`/`formBeforeUpdate`/`relationExtendManageQuery` hooks, bulk delete runs each record's lifecycle hooks, and the Settings model binds to a settings screen through the same schema pipeline.
|
||||||
|
|
||||||
**Plans**: 4/12 plans executed
|
**Plans**: 5/12 plans executed
|
||||||
**Research flag:** yes
|
**Research flag:** yes
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
@@ -393,7 +393,7 @@ Plans:
|
|||||||
- [x] 09-04-PLAN.md — Compile the list contract and the allowlisted query engine
|
- [x] 09-04-PLAN.md — Compile the list contract and the allowlisted query engine
|
||||||
|
|
||||||
**Wave 5** *(blocked on Wave 4 completion)*
|
**Wave 5** *(blocked on Wave 4 completion)*
|
||||||
- [ ] 09-05-PLAN.md — Deliver schema-projected CRUD and transactional bulk deletion
|
- [x] 09-05-PLAN.md — Deliver schema-projected CRUD and transactional bulk deletion
|
||||||
|
|
||||||
**Wave 6** *(blocked on Wave 5 completion)*
|
**Wave 6** *(blocked on Wave 5 completion)*
|
||||||
- [ ] 09-06-PLAN.md — Port the Albums admin surface and the collection boundary
|
- [ ] 09-06-PLAN.md — Port the Albums admin surface and the collection boundary
|
||||||
@@ -529,7 +529,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
|
|||||||
| 6. HTTP routing, auth groups and rate limiting | 14/14 | Complete | 2026-09-21 |
|
| 6. HTTP routing, auth groups and rate limiting | 14/14 | Complete | 2026-09-21 |
|
||||||
| 7. User plugin and authentication | 8/8 | Complete | 2026-09-23 |
|
| 7. User plugin and authentication | 8/8 | Complete | 2026-09-23 |
|
||||||
| 8. OAuth2.1 authorization server | 10/10 | Complete | 2026-09-23 |
|
| 8. OAuth2.1 authorization server | 10/10 | Complete | 2026-09-23 |
|
||||||
| 9. Backend admin authentication and schema pipeline | 4/12 | In Progress| |
|
| 9. Backend admin authentication and schema pipeline | 5/12 | In Progress| |
|
||||||
| 10. Admin Vue SPA | 0/TBD | Not started | - |
|
| 10. Admin Vue SPA | 0/TBD | Not started | - |
|
||||||
| 11. Jobs, realtime and search infrastructure | 0/TBD | Not started | - |
|
| 11. Jobs, realtime and search infrastructure | 0/TBD | Not started | - |
|
||||||
| 12. Płytarium API — Collections and Albums | 0/TBD | Not started | - |
|
| 12. Płytarium API — Collections and Albums | 0/TBD | Not started | - |
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ milestone: v1.0
|
|||||||
current_phase: 09
|
current_phase: 09
|
||||||
current_phase_name: Backend admin authentication and schema pipeline
|
current_phase_name: Backend admin authentication and schema pipeline
|
||||||
status: executing
|
status: executing
|
||||||
stopped_at: Completed 09-04-PLAN.md
|
stopped_at: Completed 09-05-PLAN.md
|
||||||
last_updated: "2026-09-24T17:06:46.487Z"
|
last_updated: "2026-09-24T17:46:54.525Z"
|
||||||
last_activity: 2026-09-24
|
last_activity: 2026-09-24
|
||||||
last_activity_desc: Phase 09 execution started
|
last_activity_desc: Phase 09 execution started
|
||||||
state_head: 3efdcc1c59a94533f28427495bfe0a646aa3fd4e
|
state_head: 50754808f61071e23746f3f36dde8a292a18360b
|
||||||
progress:
|
progress:
|
||||||
total_phases: 15
|
total_phases: 15
|
||||||
completed_phases: 8
|
completed_phases: 8
|
||||||
@@ -29,7 +29,7 @@ See: .planning/PROJECT.md (updated 2026-09-16)
|
|||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 09 (Backend admin authentication and schema pipeline) — EXECUTING
|
Phase: 09 (Backend admin authentication and schema pipeline) — EXECUTING
|
||||||
Plan: 5 of 12
|
Plan: 6 of 12
|
||||||
Status: Ready to execute
|
Status: Ready to execute
|
||||||
Last activity: 2026-09-24 — Phase 09 execution started
|
Last activity: 2026-09-24 — Phase 09 execution started
|
||||||
|
|
||||||
@@ -113,6 +113,7 @@ Progress: [██████████] 100%
|
|||||||
| Phase 09 P02 | 22 min | 3 tasks | 14 files |
|
| Phase 09 P02 | 22 min | 3 tasks | 14 files |
|
||||||
| Phase 09 P03 | 25min | 3 tasks | 10 files |
|
| Phase 09 P03 | 25min | 3 tasks | 10 files |
|
||||||
| Phase 09 P04 | 36min | 3 tasks | 13 files |
|
| Phase 09 P04 | 36min | 3 tasks | 13 files |
|
||||||
|
| Phase 09 P05 | 25min | 3 tasks | 8 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -287,6 +288,10 @@ Recent decisions affecting current work:
|
|||||||
- [Phase 09]: list_toolbar, recordUrl, and showCheckboxes compile to create, update, and delete
|
- [Phase 09]: list_toolbar, recordUrl, and showCheckboxes compile to create, update, and delete
|
||||||
- [Phase 09]: A conditions key is a boot error; a model scope must be listed by FilterScopes()
|
- [Phase 09]: A conditions key is a boot error; a model scope must be listed by FilterScopes()
|
||||||
- [Phase 09]: Admin list meta uses D-11 page, while lagoon.Paginate still computes last_page
|
- [Phase 09]: Admin list meta uses D-11 page, while lagoon.Paginate still computes last_page
|
||||||
|
- [Phase 09]: Writable admin fields are bound to gorm columns at activation; id, timestamps, scope, and system flags are never fillable
|
||||||
|
- [Phase 09]: Show and update use one not-found body for missing and out-of-scope rows; delete of an absent row is deleted 0 and does not run hooks
|
||||||
|
- [Phase 09]: A bulk selection that matches no scoped row is a no-op; a mixed present and absent selection is a 409 and rolls back
|
||||||
|
- [Phase 09]: Controller hook failures return an opaque lifecycle error and do not echo the hook text
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -309,6 +314,6 @@ Items acknowledged and carried forward from previous milestone close:
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-09-24T17:06:46.102Z
|
Last session: 2026-09-24T17:46:43.371Z
|
||||||
Stopped at: Completed 09-04-PLAN.md
|
Stopped at: Completed 09-05-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
@@ -0,0 +1,272 @@
|
|||||||
|
---
|
||||||
|
phase: 09-backend-admin-authentication-and-schema-pipeline
|
||||||
|
plan: 05
|
||||||
|
subsystem: admin
|
||||||
|
tags: [cabana, crud, bulk-delete, gorm, mass-assignment, lifecycle]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 09-backend-admin-authentication-and-schema-pipeline
|
||||||
|
provides: compiled form schema, backend permission gate, and D-10 envelopes
|
||||||
|
provides:
|
||||||
|
- Schema-projected create and update through Fill then Validate
|
||||||
|
- Permissioned show, create, update, and delete with scoped lookup
|
||||||
|
- Transactional bulk delete with duplicate, empty, retry, and concurrency rules
|
||||||
|
affects: [09-backend-admin-authentication-and-schema-pipeline, admin-api, phase-10-spa]
|
||||||
|
|
||||||
|
actuals:
|
||||||
|
tokens: 17783
|
||||||
|
tasks: 3
|
||||||
|
commits: 6
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Writable fields are bound to gorm columns at activation and projected by exact key"
|
||||||
|
- "Record mutations run Fill, BeforeValidate, Validate, then controller and model hooks in one transaction"
|
||||||
|
- "Bulk delete locks the scoped set FOR UPDATE and commits every selected row or none"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- cabana/crud.go
|
||||||
|
- cabana/crud_test.go
|
||||||
|
- cabana/crud_lifecycle_test.go
|
||||||
|
- cabana/bulk_test.go
|
||||||
|
modified:
|
||||||
|
- cabana/http.go
|
||||||
|
- cabana/registry.go
|
||||||
|
- cabana/contracts.go
|
||||||
|
- pact/capabilities.go
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Writable admin fields are bound to gorm columns at activation; id, timestamps, scope, and system flags are never fillable"
|
||||||
|
- "Show and update use one not-found body for missing and out-of-scope rows; delete of an absent row is deleted 0 and does not run hooks"
|
||||||
|
- "A bulk selection that matches no scoped row is a no-op; a mixed present and absent selection is a 409 and rolls back"
|
||||||
|
- "Controller hook failures return an opaque lifecycle error and do not echo the hook text"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Pattern: ProjectWritableFields copies only activation bindings, so request key casing and nesting cannot reach Fill"
|
||||||
|
- "Pattern: bulk ids are parsed, deduped, and sorted before a single locked transaction"
|
||||||
|
|
||||||
|
requirements-completed: [ADMIN-04]
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
- id: D1
|
||||||
|
description: Create and update project only schema-writable fields, call Fill then Validate, and return D-10 422 field errors.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_test.go#TestCRUDFillValidate
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D2
|
||||||
|
description: Unknown, cased, nested, and protected keys never change id, timestamps, scope, or system flags.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: cabana/crud_test.go#TestCRUDWritableProjection
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_test.go#TestCRUDRejectsProtectedFields
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D3
|
||||||
|
description: A model missing Fillable or Rules, or a Validate provider error, fails closed with the controller id and persists nothing.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_test.go#TestCRUDCapabilityFailure
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D4
|
||||||
|
description: Show, create, update, and delete are mounted behind the backend permission check and use D-10 envelopes.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_lifecycle_test.go#TestCRUDRecordRoutes
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_lifecycle_test.go#TestCRUDPermissions
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D5
|
||||||
|
description: Missing and out-of-scope records share one not-found or deleted-zero body, and in-scope rows stay unchanged.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_lifecycle_test.go#TestCRUDScope
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D6
|
||||||
|
description: Create, update, and delete run Before and After hooks once, in order, inside the transaction.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_lifecycle_test.go#TestCRUDHooks
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D7
|
||||||
|
description: A failing create, update, or delete hook rolls the transaction back and the HTTP body stays opaque.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/crud_lifecycle_test.go#TestCRUDRollback
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D8
|
||||||
|
description: Bulk delete rejects an empty selection, collapses duplicates, and deletes in ascending primary-key order.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/bulk_test.go#TestBulkDeleteEmpty
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/bulk_test.go#TestBulkDeleteDuplicates
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/bulk_test.go#TestBulkDeleteOrder
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D9
|
||||||
|
description: Repeating a completed bulk delete, or naming only out-of-scope rows, returns deleted 0 and does not run hooks.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/bulk_test.go#TestBulkDeleteIdempotent
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D10
|
||||||
|
description: A mixed selection, hook error, or cancellation rolls the whole batch back, and two concurrent deletes remove each row once.
|
||||||
|
requirement: ADMIN-04
|
||||||
|
verification:
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/bulk_test.go#TestBulkDeleteRollback
|
||||||
|
status: pass
|
||||||
|
- kind: integration
|
||||||
|
ref: cabana/bulk_test.go#TestBulkDeleteConcurrent
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
|
||||||
|
duration: 25min
|
||||||
|
completed: 2026-09-24
|
||||||
|
status: complete
|
||||||
|
plan_head_before: 040f3ef81c199c82beec1ee8d4626aa4f85fe19a
|
||||||
|
plan_head_after: 50754808f61071e23746f3f36dde8a292a18360b
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 9 Plan 05: Schema-projected CRUD and atomic bulk delete Summary
|
||||||
|
|
||||||
|
**Admin create and update fill only activation-bound fields, and bulk delete locks the scoped set so every selected row commits or none do.**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 25 min
|
||||||
|
- **Started:** 2026-09-24T17:20:57Z
|
||||||
|
- **Completed:** 2026-09-24T17:45:40Z
|
||||||
|
- **Tasks:** 3
|
||||||
|
- **Files modified:** 8
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- `ProjectWritableFields` keeps only schema fields bound to gorm columns at activation. `id`, timestamps, `scope_id`, ownership ids, and system flags never reach `lagoon.Fill`, even when the JSON key is cased or nested.
|
||||||
|
- Create and update run Fill, `BeforeValidate`, then `lagoon.Validate` (YAML `required` merged onto `Rules()`) before persistence. Validation errors are D-10 `validation_failed` with field messages. A missing Fillable/Rules method or a Validate provider error does not insert.
|
||||||
|
- `GET/POST/PUT/DELETE /_admin/api/v1/{vendor}/{plugin}/{controller}` record routes sit behind the backend group and `protect`, so a forbidden caller is 403 before the id or body is read. Show and update of a missing or out-of-scope id share one `not_found` body. Delete of an absent id returns `deleted: 0` and does not run hooks.
|
||||||
|
- Create, update, and delete call the matching `FormBefore*` / `FormAfter*` hook once around the GORM callbacks, inside one transaction. A hook error rolls back and the response is `Server error` without the hook text.
|
||||||
|
- `POST .../bulk-delete` rejects an empty `ids` list with 422, dedupes, sorts by primary key, and locks the scoped rows `FOR UPDATE`. A wholly absent selection returns `deleted: 0`. A mixed present/absent selection is 409 and rolls back. Concurrent identical requests delete each row once.
|
||||||
|
|
||||||
|
## TDD Gate Compliance
|
||||||
|
|
||||||
|
Each task has a `test(09-05)` commit that failed on the named assertion, then a `feat(09-05)` commit. `gsd_run check tdd-red-evidence` returned `RED_EVIDENCE_OK` for `TestCRUDFillValidate`, `TestCRUDRecordRoutes`, and `TestBulkDeleteEmpty` before the matching implementation. No refactor commit was needed.
|
||||||
|
|
||||||
|
| Task | RED | GREEN | REFACTOR |
|
||||||
|
|------|-----|-------|----------|
|
||||||
|
| 1 Fill/Validate | 1e14da7 | 578bdc8 | — |
|
||||||
|
| 2 Record lifecycle | 94814d9 | e3e1c25 | — |
|
||||||
|
| 3 Bulk delete | 247c323 | 5075480 | — |
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically. `commits: 6` is `git rev-list --count` from `040f3ef81c199c82beec1ee8d4626aa4f85fe19a` to `50754808f61071e23746f3f36dde8a292a18360b`.
|
||||||
|
|
||||||
|
1. **Task 1: Project writable fields and enforce Fill/Validate (RED)** - `1e14da7` (test)
|
||||||
|
2. **Task 1: Project writable fields and enforce Fill/Validate (GREEN)** - `578bdc8` (feat)
|
||||||
|
3. **Task 2: Wire scoped record CRUD with mandatory lifecycle hooks (RED)** - `94814d9` (test)
|
||||||
|
4. **Task 2: Wire scoped record CRUD with mandatory lifecycle hooks (GREEN)** - `e3e1c25` (feat)
|
||||||
|
5. **Task 3: Make bulk deletion deterministic, retry-safe, and atomic (RED)** - `247c323` (test)
|
||||||
|
6. **Task 3: Make bulk deletion deterministic, retry-safe, and atomic (GREEN)** - `5075480` (feat)
|
||||||
|
|
||||||
|
**Plan metadata:** included in the docs commit for this summary
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `cabana/crud.go` - CRUDService, writable projection, record lifecycle, and locked bulk delete
|
||||||
|
- `cabana/http.go` - show, create, update, delete, and bulk-delete routes after the permission check
|
||||||
|
- `cabana/registry.go` - binds writable fields while compiling a controller
|
||||||
|
- `cabana/contracts.go` - `WritableField` on the compiled controller
|
||||||
|
- `cabana/crud_test.go` - Fill/Validate, projection, protected fields, and capability tests
|
||||||
|
- `cabana/crud_lifecycle_test.go` - routes, permissions, scope, hooks, and rollback
|
||||||
|
- `cabana/bulk_test.go` - empty, duplicate, order, retry, rollback, and concurrency
|
||||||
|
- `pact/capabilities.go` - FormAfterCreate, FormAfterUpdate, FormBeforeDelete, FormAfterDelete
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- Activation binds a scalar form field to the gorm column of the same name. Protected columns are omitted from that list rather than copied and then dropped.
|
||||||
|
- YAML `required: true` is appended to model `Rules()` and never replaces a stricter rule. Validate reads the model after `BeforeValidate`, so a hook can still clear a value and fail required.
|
||||||
|
- Show and update answer missing and out-of-scope ids with the same 404. Delete answers both with `deleted: 0` so a retry of a completed delete does not rerun hooks and does not reveal scope.
|
||||||
|
- Bulk delete uses `ListExtendQuery`. If the locked row count is zero, the result is `deleted: 0`. If it is greater than zero but short of the normalized ids, the response is `conflict` and the transaction rolls back.
|
||||||
|
- Hook and database errors become `cabana: controller <id> failed`. The HTTP body stays `Server error`.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 2 - Missing Critical] Added the After and delete controller hooks**
|
||||||
|
- **Found during:** Task 2 (scoped record lifecycle)
|
||||||
|
- **Issue:** D-13 named `FormBeforeCreate` and `FormBeforeUpdate` only. The plan also requires Before/After hooks for create, update, and delete, once each.
|
||||||
|
- **Fix:** Added `FormAfterCreate`, `FormAfterUpdate`, `FormBeforeDelete`, and `FormAfterDelete` next to the existing pact hooks and call each implemented hook inside the transaction.
|
||||||
|
- **Files modified:** `pact/capabilities.go`, `cabana/crud.go`
|
||||||
|
- **Verification:** `TestCRUDHooks` and `TestCRUDRollback`
|
||||||
|
- **Committed in:** `94814d9` (interfaces) and `e3e1c25` (calls)
|
||||||
|
|
||||||
|
**2. [Rule 2 - Missing Critical] Stored the writable binding on the compiled controller**
|
||||||
|
- **Found during:** Task 1 (Fill/Validate)
|
||||||
|
- **Issue:** The plan's file list did not include `contracts.go`, but the binding has to survive activation and be readable without reflecting over request keys.
|
||||||
|
- **Fix:** Added `Writable []WritableField` and fill it from `BindWritableFields` during `compileRegistry`.
|
||||||
|
- **Files modified:** `cabana/contracts.go`, `cabana/registry.go`
|
||||||
|
- **Verification:** `TestCRUDWritableProjection`
|
||||||
|
- **Committed in:** `1e14da7` and `578bdc8`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 2 auto-fixed (2 missing critical)
|
||||||
|
**Impact on plan:** Both were required to enforce the mass-assignment and lifecycle contracts. No new route family or dependency.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None - no external service configuration required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
Ready for 09-06. Record and bulk routes are in place for every compiled controller that exposes `NewRecord`, `Fillable`, and `Rules`. Relation link/unlink and settings upsert are still later plans. `ADMIN-04` stays pending in `REQUIREMENTS.md` because 09-06, 09-07, 09-08, 09-09, 09-10, and 09-12 also declare it.
|
||||||
|
|
||||||
|
`go test ./cabana -run '^(TestCRUD|TestBulkDelete)' -count=1` passed.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- FOUND: cabana/crud.go
|
||||||
|
- FOUND: cabana/bulk_test.go
|
||||||
|
- FOUND: cabana/crud_test.go
|
||||||
|
- FOUND: cabana/crud_lifecycle_test.go
|
||||||
|
- FOUND: 1e14da7
|
||||||
|
- FOUND: 578bdc8
|
||||||
|
- FOUND: 94814d9
|
||||||
|
- FOUND: e3e1c25
|
||||||
|
- FOUND: 247c323
|
||||||
|
- FOUND: 5075480
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 09-backend-admin-authentication-and-schema-pipeline*
|
||||||
|
*Completed: 2026-09-24*
|
||||||
Reference in New Issue
Block a user