|
3117 | 3117 | }, |
3118 | 3118 | { |
3119 | 3119 | "id": "access-security.anonymous-floor-v18-doors", |
3120 | | - "title": "The anonymous floor answers 401 FIRST on the doors v18 added to it — /notifications (was 501), non-POST /keys (was 405), share-link management (was 501), every /ui face, /openapi.json and /docs, every /i18n face and the settings family — while the token faces and the public-form submit stay anonymous and the submit echoes only {id}", |
| 3120 | + "title": "The anonymous floor answers 401 FIRST on the doors v18 added to it — /notifications (was 501), non-POST /keys (was 405), share-link management (was 501), /openapi.json and /docs, every /i18n face and the settings family — while the token faces and the public-form submit stay anonymous and the submit echoes only {id}", |
3121 | 3121 | "since": "v18", |
3122 | 3122 | "status": "active", |
3123 | 3123 | "revision": 1, |
|
3132 | 3132 | "requires": [ |
3133 | 3133 | "a fresh boot of the showcase: `pnpm dev -- --fresh -p PORT --seed-admin` (ephemeral DB; the seeded admin is printed)", |
3134 | 3134 | "the showcase's published public form slug (GET /api/v1/meta/form as admin lists it)" |
| 3135 | + ], |
| 3136 | + "knownGaps": [ |
| 3137 | + "the dispatcher `/ui` domain (also floored by 23225) is NOT mounted over HonoServer on a stock `os dev` / `os serve` — GET /api/v1/ui/... answers 404 ENDPOINT_NOT_FOUND to the admin too — so it is not driven here; it is reachable only on a dispatcher-only (hosted) kernel and is pinned by the dogfood sweep", |
| 3138 | + "the dispatcher mounts only POST /keys on HonoServer (packages/runtime/src/dispatcher-plugin.ts), so a non-POST /keys never reaches the domain's floor on a stock boot: the HonoServer fallback answers it 405 METHOD_NOT_ALLOWED (packages/plugins/plugin-hono-server/src/adapter.ts unmatchedResponse) — run 2026-10-16 measured exactly that; the clause stays as the 23225 contract states it, so a 405 there is a FAIL, not a re-point" |
3135 | 3139 | ] |
3136 | 3140 | }, |
3137 | 3141 | "steps": [ |
3138 | | - "with NO credentials call: GET /api/v1/notifications, GET /api/v1/keys, GET /api/v1/share-links, GET /api/v1/ui/view/showcase_task, GET /api/v1/openapi.json, GET /api/v1/docs, GET /api/v1/i18n/locales, GET /api/settings/branding", |
| 3142 | + "with NO credentials call: GET /api/v1/notifications, GET /api/v1/keys, GET /api/v1/share-links, GET /api/v1/openapi.json, GET /api/v1/docs, GET /api/v1/i18n/locales, GET /api/settings/branding", |
3139 | 3143 | "with no credentials call a token face: GET /api/v1/share-links/BOGUS/resolve", |
3140 | 3144 | "with no credentials POST /api/v1/forms/SLUG/submit with a valid body", |
3141 | 3145 | "repeat two of the 401 calls as admin to prove the door itself serves" |
|
3274 | 3278 | "surface": "api", |
3275 | 3279 | "personas": [ |
3276 | 3280 | "seeded admin (admin@objectos.ai / admin123) — the Default Organization owner and platform admin on a fresh boot", |
3277 | | - "org member (a second sign-up on the same boot — joins the Default Organization as `member`, not platform admin)" |
| 3281 | + "org member — created by the admin with POST /api/v1/auth/admin/create-user (stock showcase self-registration is closed: audience posture invite_only answers sign-up 403 SELF_REGISTRATION_CLOSED); joins the Default Organization as `member`, not platform admin, and lands mustChangePassword:true, i.e. a HELD session until it changes its password (POST /api/v1/auth/change-password)" |
3278 | 3282 | ], |
3279 | 3283 | "fixtures": { |
3280 | 3284 | "app": "showcase", |
3281 | 3285 | "requires": [ |
3282 | 3286 | "a fresh boot of the showcase: `pnpm dev -- --fresh -p PORT --seed-admin` (ephemeral DB; the seeded admin is printed)", |
3283 | | - "a scratch list view (PUT /api/v1/meta/view/qa_gated_view — view is overlay-allowed on stock showcase) with requiredPermissions naming a capability the member lacks", |
| 3287 | + "a scratch list view (PUT /api/v1/meta/view/showcase_task.qa_gated_view — view is overlay-allowed on stock showcase; a view name is dotted OBJECT.NAME) with requiredPermissions naming a capability the member lacks", |
3284 | 3288 | "a member granted setup.access but not studio.access / manage_metadata (a scratch permission set assigned through sys_user_permission_set)" |
3285 | 3289 | ] |
3286 | 3290 | }, |
3287 | 3291 | "steps": [ |
3288 | 3292 | "as the setup.access-only member: GET /api/v1/meta/object/showcase_task/history, /audit, /diff; GET /api/v1/packages/com.example.showcase/commits", |
3289 | | - "as a member without the capability: GET /api/v1/meta/view (list) and GET /api/v1/meta/view/qa_gated_view, plus /published, /layers, ?state=draft, /history", |
| 3293 | + "as a member without the capability: GET /api/v1/meta/view (list) and GET /api/v1/meta/view/showcase_task.qa_gated_view, plus /published, /layers, ?state=draft, /history", |
3290 | 3294 | "as admin: the same reads (control); then delete the scratch view" |
3291 | 3295 | ], |
3292 | 3296 | "acceptance": [ |
|
3344 | 3348 | "surface": "api", |
3345 | 3349 | "personas": [ |
3346 | 3350 | "seeded admin (admin@objectos.ai / admin123) — the Default Organization owner and platform admin on a fresh boot", |
3347 | | - "org member (a second sign-up on the same boot — joins the Default Organization as `member`, not platform admin)", |
| 3351 | + "org member — created by the admin with POST /api/v1/auth/admin/create-user (stock showcase self-registration is closed: audience posture invite_only answers sign-up 403 SELF_REGISTRATION_CLOSED); joins the Default Organization as `member`, not platform admin, and lands mustChangePassword:true, i.e. a HELD session until it changes its password (POST /api/v1/auth/change-password)", |
3348 | 3352 | "anonymous caller (no cookie, no bearer, no x-api-key)" |
3349 | 3353 | ], |
3350 | 3354 | "fixtures": { |
|
3498 | 3502 | "surface": "api", |
3499 | 3503 | "personas": [ |
3500 | 3504 | "seeded admin (admin@objectos.ai / admin123) — the Default Organization owner and platform admin on a fresh boot", |
3501 | | - "org member (a second sign-up on the same boot — joins the Default Organization as `member`, not platform admin)" |
| 3505 | + "org member — created by the admin with POST /api/v1/auth/admin/create-user (stock showcase self-registration is closed: audience posture invite_only answers sign-up 403 SELF_REGISTRATION_CLOSED); joins the Default Organization as `member`, not platform admin, and lands mustChangePassword:true, i.e. a HELD session until it changes its password (POST /api/v1/auth/change-password)" |
3502 | 3506 | ], |
3503 | 3507 | "fixtures": { |
3504 | 3508 | "app": "showcase", |
|
3522 | 3526 | "evidence": "the vitest summary line per pin file, with the package name and the subject sha" |
3523 | 3527 | }, |
3524 | 3528 | { |
3525 | | - "clause": "permission_set_id → 400 INVALID_FIELD; a second identical grant → 409 UNIQUE_VIOLATION; valid_until <= valid_from → 400 VALIDATION_FAILED at valid_until (rule validity_window_order)", |
| 3529 | + "clause": "permission_set_id → 400 INVALID_FIELD; a second identical grant → 409 UNIQUE_VIOLATION", |
3526 | 3530 | "oracle": "api", |
3527 | 3531 | "verify": "status + code + located field per arm", |
3528 | | - "evidence": "three refusal bodies" |
| 3532 | + "evidence": "two refusal bodies" |
| 3533 | + }, |
| 3534 | + { |
| 3535 | + "clause": "an INSERT with valid_until <= valid_from is refused as the rule's VIOLATION: 400 VALIDATION_FAILED at valid_until with constraint.rule validity_window_order, constraint.reason NOT `unevaluable`, and the rule's authored message (\"Valid Until must be later than Valid From …\") — an unevaluable-predicate refusal is a FAIL even though it also answers 400", |
| 3536 | + "oracle": "api", |
| 3537 | + "verify": "fields[0].constraint + message on the inverted-window insert; a valid window inserts 201 (control)", |
| 3538 | + "evidence": "the refusal body + the control" |
3529 | 3539 | }, |
3530 | 3540 | { |
3531 | 3541 | "clause": "a non-system insert naming someone else as granted_by stores the CALLER", |
|
3568 | 3578 | "surface": "api", |
3569 | 3579 | "personas": [ |
3570 | 3580 | "seeded admin (admin@objectos.ai / admin123) — the Default Organization owner and platform admin on a fresh boot", |
3571 | | - "org member (a second sign-up on the same boot — joins the Default Organization as `member`, not platform admin)" |
| 3581 | + "org member — created by the admin with POST /api/v1/auth/admin/create-user (stock showcase self-registration is closed: audience posture invite_only answers sign-up 403 SELF_REGISTRATION_CLOSED); joins the Default Organization as `member`, not platform admin, and lands mustChangePassword:true, i.e. a HELD session until it changes its password (POST /api/v1/auth/change-password)" |
3572 | 3582 | ], |
3573 | 3583 | "fixtures": { |
3574 | 3584 | "app": "showcase", |
|
3645 | 3655 | "surface": "api", |
3646 | 3656 | "personas": [ |
3647 | 3657 | "seeded admin (admin@objectos.ai / admin123) — the Default Organization owner and platform admin on a fresh boot", |
3648 | | - "org member (a second sign-up on the same boot — joins the Default Organization as `member`, not platform admin)" |
| 3658 | + "org member — created by the admin with POST /api/v1/auth/admin/create-user (stock showcase self-registration is closed: audience posture invite_only answers sign-up 403 SELF_REGISTRATION_CLOSED); joins the Default Organization as `member`, not platform admin, and lands mustChangePassword:true, i.e. a HELD session until it changes its password (POST /api/v1/auth/change-password)" |
3649 | 3659 | ], |
3650 | 3660 | "fixtures": { |
3651 | 3661 | "app": "showcase", |
|
0 commit comments