Repository navigation
Checklist platform core
github-actions[bot] edited this page Nov 12, 2026
·
1 revision
Generated by
pnpm gen:checklist-statusfromdocs/qa/platform-checklist/areas/*.json. ⛔ Do not edit this page — edits go to the area JSON and this page follows on the next run. This page isChecklist-platform-core.
Platform core — boot, health, console shell, metadata pipeline
47 active · 0 planned
| id | title | priority | status | personas |
|---|---|---|---|---|
platform-core.boot-health |
Showcase boots clean: health + ready 200, no degraded startup banners, console + app metadata served | P0 | active | — |
platform-core.seed-integrity |
Seed integrity: row counts match the authored seed, values land verbatim, replay is idempotent | P0 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.console-login |
Seeded admin signs in through the console; the session survives reload and re-authenticates cleanly after expiry | P0 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.nav-surfaces-render |
Every showcase nav surface renders without page errors, and failures surface the error boundary — never a blank page | P0 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.metadata-registry-serving |
The metadata registry is served over REST: /meta lists every registered type with its spec-derived create seed | P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.metadata-authoring-roundtrip |
Metadata authoring round-trip: draft → publish on a WRITABLE package; read-only packages and locked types are server-side refused | P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.builtin-apps-nav-render |
The built-in apps a stock boot REGISTERS (Setup / Account) render every merged-nav destination; app-level and entry-level gates are enforced, not errored — and Studio's deliberate absence is asserted, never hunted | P0 | active | seeded admin (admin@objectos.ai / admin123), a plain member — the SEEDED persona Mei (phone.demo@example.com / showcase123; examples/app-showcase/src/security/demo-personas.ts PHONE_DEMO_USER), who holds no position, so only the member_default baseline and neither setup.access nor studio.access. Not a fresh sign-up: the stock invite_only posture refuses an uninvited one 403 SELF_REGISTRATION_CLOSED |
platform-core.settings-hub-roundtrip |
Settings hub round-trip: a value saves, PERSISTS, reaches an observable consumer, audits, env-locks, tests honestly, and stores secrets as handles served MASKED — anonymous denied | P1 | active | seeded admin (admin@objectos.ai / admin123 — holds setup.access/setup.write/manage_platform_settings), anonymous |
platform-core.package-lifecycle-enable-disable |
Package lifecycle: disable stops serving, enable restores, uninstall de-registers, commits grow per publish and revert restores the prior published shape | P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.notification-center |
Notification center (bell / InboxPopover): badge counts distinct unread topics + pending approvals, repeats coalesce, per-group and global mark-read drop the badge | P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.shell-nav-personalization |
Shell nav personalization: sidebar collapse, pins and the user's pinned order, favorites and recents each persist and stay navigable across reload; the header's crumbs follow the route and rebuild on reload; the authored menu keeps the app's order | P2 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.app-management-toggle |
App management: the launcher/App Switcher filters by active+hidden, isDefault drives post-login landing, and AppManagementPage writes through the metadata API — a code-package app refuses Disable/Set-default with an error toast, and its Delete is a reset:false no-op the page must not report as a deletion | P2 | active | seeded admin (admin@objectos.ai / admin123), a plain member (invite + sign-up — the stock auth posture is invite_only, so a self-service sign-up is refused; member_default) |
platform-core.docs-audience-gate |
Documentation audience gating (book + doc): the tree endpoint and the doc read layer gate on ONE semantics — public/org/permissionSet, fail-closed — and an unclaimed doc never leaks through a public book | P1 | active | anonymous (no session), authenticated member who does NOT hold the gating permission set, authenticated member who DOES hold the gating permission set, seeded admin |
platform-core.interrupted-migration-boot-report |
Boot-time migration-journal scan: an interrupted run (started ∧ ¬done) is reported at kernel:ready with the exact os migrate resume prescription, boot PROCEEDS without resuming, and the two quiet-degradation arms (no journal object → silent; scan THROWS → 'could not check' warning) stay distinguishable |
P2 | active | operator (local shell) |
platform-core.manifest-install-contract |
The package manifest is enforced at the install boundary: an incompatible engines range is refused before the registry write, the namespace gate holds ownership, and a namespace-less runtime package has one derived |
P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.activation-ledger-registration-home |
The activation ledger's registration home: sys_metadata_activation is registered by PlatformObjectsPlugin under its OWN manifest, so packaged disable works with or without the automation service — one owner, datasource binding carried across the move | P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.activation-ledger-row-contract |
sys_metadata_activation row contract: reads open / generic-data-API writes 405, one row per (metadata_type, package_id, name) with NO tenant column on the table at all, re-enable updates never deletes, and rows exist ONLY for the metadata types a shipped door writes — flow, action, position, permission, sharing_rule, webhook, queue, assignment_rule (the ADR-0126 scope wall, as ADR-0131 D2, D3 and D6 and ADR-0142 D1 and D5 widen it) | P2 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.packaged-object-extend-only |
Packaged objects are extend-only (Regime E): an extension package's fields merge additively and round-trip on showcase_account, while an in-place field add on the packaged object is refused server-side at both write doors — and the collision-refusal half of the docs claim does not exist yet | P2 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.marketplace-install-local-lifecycle |
Marketplace install-local: the wiring matrix mounts the right arms per OS_CLOUD_URL, the air-gapped inline install works with NO control plane, reseed/purge touch exactly the sample rows, every mutating door is manage_metadata-gated both sides, and the listing projects installedBy/storageDir per principal | P1 | active | seeded admin (admin@objectos.ai / admin123 — admin_full_access carries manage_metadata), a plain member, created by the admin (POST /api/v1/auth/admin/create-user) — the stock audience posture is invite_only (packages/plugins/plugin-auth/src/audience-posture.ts), so a fresh self sign-up is refused; member_default holds NO manage_metadata. Measured at 756220c4 the create-user answer read membershipCreated:false while the account then held sys_member role member, so prove the persona from its own session, never from that flag, anonymous, operator (local shell — the os package install door) |
platform-core.marketplace-console-honesty |
Marketplace console honesty: nav entries live and die with their capability, the disabled state renders the configuration conclusion (never a red 'failed to load') for every viewer ahead of the admin guard, Installed Apps drives the real same-origin lifecycle, and an enabled runtime turns a non-admin away with access-denied | P2 | active | seeded admin (admin@objectos.ai / admin123), a plain member (invite + sign-up — the stock auth posture is invite_only, so a self-service sign-up is refused; member_default) |
platform-core.runtime-config-boot-read |
Runtime config boot read: GET /api/v1/runtime/config answers 200 ANONYMOUSLY with cloud URL, capability flags, branding and telemetry posture; the legacy /api/v1/studio/runtime-config alias is byte-identical (same handler); nothing credential-shaped is in the body | P1 | active | anonymous, seeded admin (control only) |
platform-core.docs-portal-render |
Docs portal render: /docs lists the installed corpus, a doc body renders with working intra-corpus links, a flat-doc URL redirects to its canonical in-book path, the per-app index scopes to one package, and a lesser persona's rendered tree equals the API's pruned subset — never a blank region | P1 | active | seeded admin (admin@objectos.ai / admin123), a plain member (invite + sign-up — the stock auth posture is invite_only, so a self-service sign-up is refused; member_default) |
platform-core.url-overlay-contract |
Reserved URL params (ADR-0054 C3): recordId drawer and form overlay push so Back closes them, record tabs push one entry on leaving Overview and replace after it, palette/shortcuts replace so Back never pages through chrome, formObject/formLink pre-link a child create, ?related cold-loads a record tab, the from trail keeps a clickable path back, and a recordId+recordObject mismatch fails closed | P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.keyboard-shortcut-surface |
Keyboard shortcut surface: ? and ?shortcuts=1 open the dialog and Esc closes it, typing in an input never triggers it, the dialog lists exactly the shortcuts whose handler is mounted and every listed one fires (⌘K, ⌘/Ctrl+B shown as ⌘B, Esc, ?), the five formerly advertised dead accelerators (⌘/, N, R, ⌘E, ⌘D) are neither listed nor bound, and the AI-chat pair ⌘⇧O / ⌘⇧S is listed only on the page that handles it (objectui#11674) |
P2 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.home-admin-cluster-links |
Shell-hard-coded Administration targets + the retired System hub: every Administration target URL resolves to a real page (no RouteNotFound, no RecordDetailView for an object named 'system'), /apps/:app/system lands on the settings hub in one hop and every hub entry resolves, the five legacy system/* URLs redirect (users and organizations to their object routes, roles, positions and permissions to Studio's All metadata catalog in its environment scope), and a member's shell offers no Administration entry | P1 | active | seeded admin (admin@objectos.ai / admin123 — isWorkspaceAdmin), a plain member (invite + sign-up — the stock auth posture is invite_only, so a self-service sign-up is refused; member_default) |
platform-core.lifecycle-retention-sweep |
ADR-0057 lifecycle sweep: backdated telemetry rows past retention are reaped BOUNDED under a system context on the hourly sweep, onlyWhen scoping spares live rows, an archive-declaring object is NEVER hot-deleted unarchived (retained + reported archive-pending when no archive datasource exists), the transient class stays on the primary, and OS_LIFECYCLE_DISABLED=1 disarms the sweep | P1 | active | operator (local shell + direct sqlite access), seeded admin (API reads) |
platform-core.seed-mode-matrix |
Seed mode matrix (insert/update/upsert/replace/ignore): each mode does exactly its verb through the ONE SeedLoaderService, no-op replays skip instead of churning, ignore reports skips — and replace inserts and deletes nothing, DECLARED and IMPLEMENTED alike (no caller clears the table): its posture is scored as bare insert, never ticked as scoped deletion |
P1 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.theme-mode-persistence |
Theme mode: dark/light apply the root class immediately and survive reload via localStorage (object-ui-theme, the console shell's storage key); system/auto resolves the OS preference at evaluation time (#2942 — never a dead 'auto' class); no half-themed surface after a toggle | P2 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.console-installability-indicators |
Console installability + connectivity indicators: the PWA manifest is a runtime-branded blob injected at boot, the offline pill appears on connectivity loss and clears on restore, the connection status chip shows transient/error states honestly — and NO service worker is registered on a stock console (caching is opt-in via useETagCache) | P2 | active | seeded admin (admin@objectos.ai / admin123) |
platform-core.settings-audit-secret-fingerprint |
The settings audit trail keeps no fingerprint of a secret-valued setting that a reader can match offline: both ledgers record the platform's keyed digest or none, never the value or an unkeyed hash, so a caller who can only read the audit rows learns that the secret changed and nothing about its value | P1 | active | seeded admin (admin@objectos.ai / admin123): writes the secret and reads both audit ledgers, a caller who can READ the audit rows but holds no server key: the reader this rule protects against. The rows are the same bytes for every reader, so the run plays this reader by checking the captured rows OFFLINE, with nothing but the value it wrote |
platform-core.v18-boot-refusals |
A v18 server refuses to boot rather than serve wrongly: against a 17.x-shaped database (a physical organization_id on a non-tenant table, no verified ADR-0131 ceremony marker) it stops before listening with ORGANIZATION_OWNERSHIP_MIGRATION_REQUIRED, naming the tables and the ownership ceremony's plan and apply, and with security on but no identity objects it stops with AuthzIdentityObjectsMissingError | P0 | active | metadata author running the CLI in a scratch copy of the showcase app (no server needed) |
platform-core.protocol-18-handshake-and-stored-replay |
Protocol 18 upgrade surfaces: a package declaring engines.protocol "^17" is refused 422 OS_PROTOCOL_INCOMPATIBLE naming os migrate meta --from 17 ("^18" is admitted), a stored v17-shaped row is served canonical while a PUT of the same old shape is refused at parse, and a "^18" artifact built before a retirement boots with one warn per replayed conversion |
P1 | active | seeded admin (admin@objectos.ai / admin123) — the Default Organization owner and platform admin on a fresh boot, metadata author running the CLI in a scratch copy of the showcase app (no server needed) |
platform-core.settings-organization-isolation-and-platform-rung |
Settings on v18: a global-scope key is stored in sys_platform_setting (readable through /data only with manage_platform_settings), and under a walled posture one organization's tenant save or lock does not change or lock another's, with a data-API read of sys_setting filtered to readable namespaces | P1 | active | seeded admin (admin@objectos.ai / admin123) — the Default Organization owner and platform admin on a fresh boot, 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), org owner holding manage_metadata who is NOT platform admin — walled-posture legs only |
platform-core.serve-composition-v18 |
os serve composition on v18: unclaimed top-level items of a packages[] config are served under manifest.id with a warn line, an app shipping its own default sys_organization record page boots, a host datasourceMapping is installed before the first schema sync, a production host with no storage refuses to boot naming three remedies, and /_console/ answers 503 with the remedy when the console is not built |
P2 | active | metadata author running the CLI in a scratch copy of the showcase app (no server needed) |
platform-core.customization-pair-ensure-door |
POST /packages/:id/ensure-customization is the one idempotent creation path of .custom — explicit _custom, a ^major dependency, 201 then 200, walled 403 — and a base is not uninstalled while its pair is installed | P1 | active | admin (holds manage_metadata; single posture), member (no manage_metadata) |
platform-core.setup-metadata-redirects-to-studio |
Setup's metadata URLs open Studio's All metadata area in one hop, the query naming the leg, while every datasource URL stays in Setup; the retired Packaged automation bookmark opens Studio's Automations pillar | P2 | active | admin |
platform-core.package-export-round-trip |
A deployment's whole ontology exports in one read and installs again on a fresh boot: GET /api/v1/packages/export answers every package the deployment's code does not register, once each and dependencies first, each entry equal to that package's own export, and os package export writes them as installable directories | P1 | active | admin (the seeded admin, holding studio.access): the reader of the export and the installer on the target boot, a member holding neither studio.access nor setup.access (the refusal leg, in its own context), anonymous (no session): the 401 leg |
platform-core.namespace-co-owner-name-refusal |
Packages that share a namespace keep each behavioural name unique across it: a second co-owner holding a sharing rule, queue, assignment rule, hook, job, app, page, dashboard, report, book, cube or tool name is refused at os validate, os build and install, while base, system and sys are exempt | P1 | active | developer at the CLI, admin (the seeded admin): the install leg |
platform-core.namespace-object-name-refusal |
A namespace never equals an object name: defineStack, os validate, os build, the install door and the publish doors all refuse a package whose namespace spells an installed object's name (or the reverse), naming both spellings | P1 | active | developer at the CLI, admin (the seeded admin): the install and publish legs |
platform-core.activation-ledger-package-key-upgrade |
An 18.3.0 database's activation ledger moves to the (metadata_type, package_id, name) key on its first boot: the package-less index is built, each package-less row binds to its one holder, ambiguous and environment rows stay null, a second boot writes nothing, and os migrate plan offers the old index as a safe replacement | P1 | active | operator at the CLI, with direct access to the database file |
platform-core.bare-name-one-holder-refusal |
A covered bare name has one package holder: installing a second package that holds a picklist, mapping, dataset, api, object-less action, function, flow, webhook, connector, email template or tool name is refused 422 naming both, agent and skill names are held per namespace, and a clash an earlier deployment already holds boots with a warning | P1 | active | admin (the seeded admin): every install |
platform-core.stored-reference-package-backfill-upgrade |
An 18.3.0 database's stored references gain the package that holds them on the first boot: grants, binding suggestions, managed sharing rules, queue members, assignment cursors, open approvals, paused runs, flow credentials, connector connections and email templates are bound to their one holder, refused names stay null with one warning per table, dispatch keys are re-keyed by package, and a second boot writes nothing | P1 | active | operator, with direct access to the database file, admin (the seeded admin): the permission parity read |
platform-core.multi-replica-package-change-refusal |
Under declared replicas on Redis a runtime package change is refused 409 MULTI_REPLICA_PACKAGE_CHANGE_REFUSED on every package door, on marketplace install-local, and on a clone that would create a customization package; nothing is written | P1 | active | seeded admin (admin@objectos.ai / admin123): every call |
platform-core.ready-cluster-driver-health |
GET /api/v1/ready reports the redis cluster driver's health under declared replicas: a cluster entry when it answers, and status degraded (still 200) when it does not; a single node's body is unchanged | P1 | active | an orchestrator probing readiness (no session) |
platform-core.cluster-membership-heartbeat |
Under declared replicas on Redis each replica keeps a membership key alive by heartbeat and lists itself in the roster; a killed replica drops out within the TTL and a stopped one at once | P2 | active | an operator reading which replicas are alive |
platform-core.settings-change-reaches-every-replica |
Under declared replicas on Redis a settings change made through one replica takes effect on the others without a restart (the settings lane) | P1 | active | seeded admin (admin@objectos.ai / admin123): the settings change, an anonymous visitor signing up or in on replica B |
platform-core.shared-redis-cache-across-replicas |
Under declared replicas on Redis the cache service is the one shared Redis cache, so a cache-backed limit such as the sign-in rate limit holds across replicas | P1 | active | an anonymous caller attempting sign-in on both replicas |