Functional Specification v1
This chapter specifies how the v1 product behaves at runtime. It translates the consolidated PRD in /prd/06-prd-v1/, the selected feature set in /prd/04-v1-feature-set-selection/, and the journey flows in /prd/03-user-journey-flows/ into implementation-facing module rules.
The canonical feature catalogue remains /prd/02-feature-specification/. The binding architecture rules remain /architecture/01-architecture-decisions/. This document fills the behavioural gap between product requirement and implementation.
7.1 — Functional specification scope
| Scope item | Included in this chapter | Source of truth |
|---|---|---|
| Functional modules | App, backend, and content-pipeline modules required for v1. | This chapter, traced to feature IDs. |
| Behavioural rules | What each module must do, reject, persist, emit, and recover from. | This chapter and /prd/02-feature-specification/. |
| State transitions | User, artwork, download, purchase, progress, and publication state movement. | This chapter, /prd/03-user-journey-flows/, /spec/07-data-layer/. |
| Data and command contracts | API endpoints, local data contracts, CLI/tooling commands, and event schemas. | /spec/06-data-model/, /spec/08-api/, /spec/13-observability/, this chapter. |
| Error handling | Recoverable states and user/system responses for v1 failure journeys. | /prd/03-user-journey-flows/ failure journeys. |
7.2 — Functional modules and behavioural rules
Each module’s “Must not do” column also inherits the cross-cutting banned UI conventions in /spec/02-product/ §2.5: no countdown timers, streak mechanics, badges, daily-reward dialogs, interstitial ads, or rate-this-app prompts during a colouring session. These apply to every UI-bearing module below.
| Module | Owns | Must do | Must not do | Traceability |
|---|---|---|---|---|
| Anonymous identity | First-launch session, profile row, account upgrade, sign-in providers. | Create an anonymous authenticated session on first launch; preserve progress during account upgrade; merge existing-account progress by bitset union. | Expose a signed-out catalogue; lose local progress during account upgrade; allow anonymous restore or purchase completion. | FEAT-ID-001 to FEAT-ID-003, FEAT-DATA-001, FEAT-API-003, JRN-P01, JRN-A08, EDGE-006, ADR-005. |
| Onboarding and retention | Welcome, cultural themes (multi-select with at least one required), audience, accessibility defaults, starter route, first-steps retention checklist. | Capture only v1 preferences; persist selected themes and audience; default always-show-numbers on; respect OS reduce-motion; surface the retention checklist on library home for the first three sessions unless dismissed. | Show a feature tour; force account creation; show a paywall before first value; render banned UI conventions (see note above); allow zero cultural themes to be persisted. | FEAT-ONB-001 to FEAT-ONB-006, FEAT-RET-001, JRN-P01, EDGE-001, EDGE-003, /spec/09-user-flows/ §9.7, /spec/22-principles/ principle 6. |
| Trust moment | The founder’s note and soft account prompt that follow first value. | Watch progress for the aha-moment threshold (first ten cells filled) and the completion event; show the founder’s note only after a qualifying milestone; offer the soft account prompt after the note; preserve dismissal state. | Show the note before the aha moment; force account creation; cite cultural notes that have not been approved. | FEAT-ONB-007, FEAT-ONB-008, FEAT-PROG-003, FEAT-PROG-004, FEAT-OPEN-001 (founder’s-note copy / OD-10), JRN-P01, JRN-A08, EDGE-006. |
| Notifications | Opt-in new-artwork push notifications and the pre-permission screen. | Show the pre-permission value screen before triggering the OS prompt; route notifications to the relevant artwork or pack surface; let Settings manage on/off state. | Fire the OS prompt without prior in-app opt-in; load behavioural ad SDKs alongside notification SDKs; emit behavioural analytics for notification opens in child mode. | FEAT-ONB-009, FEAT-NOT-001, FEAT-OPEN-003 (pre-permission copy / OD-12), /spec/20-open/ OD-07. |
| Library | Published catalogue, personalised rows, continue/downloaded states, filters. | Show RLS-published artwork; rank by selected themes and audience; show local progress and offline availability; handle offline refresh failure gracefully. | Show drafts to normal users; hide active in-progress work because of filters; rely only on remote flags for downloaded state; render banned UI conventions. | FEAT-LIB-001 to FEAT-LIB-004, FEAT-DATA-002, FEAT-API-001, JRN-P02, JRN-F06, EDGE-008. |
| Artwork detail | Artwork metadata, preview, free/owned/locked state, artist credit, cultural context. | Present title, preview, difficulty, estimated time, region count, progress, artist credit, and correct primary action. | Show unapproved cultural context; blur free/owned/locked states; parse entitlement locally. | FEAT-ART-001, FEAT-ART-002, FEAT-DATA-002, JRN-P03, JRN-P04, ADR-007. |
| Download and cache | Download URL request, bundle transfer, checksum verification, atomic cache, version reconciliation. | Use public URLs for free artwork and signed URLs for entitled premium artwork; verify checksum before cache promotion; keep offline play available once cached; parse CLRX v1 bundles against the data-model contract. | Render a partially downloaded bundle; continue with failed checksum; block colouring on network after successful download. | FEAT-DL-001, FEAT-DL-002, FEAT-CACHE-001, FEAT-CACHE-002, FEAT-NET-001, FEAT-DATA-003, JRN-P03, JRN-F04, JRN-F05, EDGE-004, EDGE-007, ADR-011. |
| Canvas engine | Rendering, zoom/pan, hit testing, region fill, feedback, canvas accessibility. | Use a single CustomPainter; build the spatial index at artwork open; persist correct fills immediately; support reduce motion, labels, pattern fills, and small-region forgiveness. | Create one widget per region; wait on sync during play; make colour the only signal; render banned UI conventions. | FEAT-CAN-001 to FEAT-CAN-004, FEAT-ACC-001 to FEAT-ACC-003, FEAT-DATA-003, JRN-P01, EDGE-003, EDGE-005, EDGE-009, ADR-003, ADR-010, ADR-012. |
| Palette | Numbered swatches, selected colour, remaining counts, highlight action. | Announce number, colour name, and remaining count; clearly mark selected and completed colours; support highlight remaining regions. | Rely on colour alone; trigger heavy animation; mutate progress from highlight action. | FEAT-PAL-001, FEAT-PAL-002, FEAT-ACC-002. |
| Progress | Local bitset, completion count, last selected colour, sync queue, completion triggers. | Store completed regions as a bitset; update count and completion locally; sync by server-side union; emit the aha-moment threshold and completion event for the Trust moment module. | Use JSON as the primary progress record; use last-write-wins; uncomplete regions as part of normal play. | FEAT-PROG-001 to FEAT-PROG-003, FEAT-DATA-004, FEAT-API-002, ADR-004. |
| Monetisation | Pack catalogue, paywall, native purchase, server receipt validation, restore. | Show content packs only; require account before purchase/restore; send receipts to backend; reflect entitlement only after validation. | Ship subscriptions, adverts, in-app currency, or client-granted entitlements in v1; render banned UI conventions on the paywall. | FEAT-IAP-001 to FEAT-IAP-004, FEAT-DATA-005, FEAT-API-004, JRN-P04, JRN-A05, JRN-F01 to JRN-F03, EDGE-007, ADR-008. |
| Settings | Account, accessibility, preferences, child mode, restore, support/reporting, and exposure of the Notifications module’s on/off state. | Persist changes; apply child-mode analytics policy immediately; expose restore and notification state; explain restricted actions. | Load behavioural ad SDKs; leave analytics identifiers active after child mode is enabled; render banned UI conventions. | FEAT-SET-001 to FEAT-SET-003, JRN-A02 to JRN-A04, JRN-F10, EDGE-002. |
| Content pipeline | Authoring, segmentation, validation, review, upload, preview, publish. | Validate bundles; record warnings/errors; require cultural review approval before publish; use admin functions for privileged writes. | Publish invalid bundles; bypass review; expose service-role credentials in tooling. | FEAT-CONT-001 to FEAT-CONT-003, FEAT-CULT-001, FEAT-ADMIN-001, FEAT-DATA-006, FEAT-API-005, JRN-P05, JRN-A07, JRN-F09, EDGE-008, EDGE-009, ADR-009. |
| Observability and release | Product events, purchase events, crash reporting, performance timers, backend logs, CI/CD release gates. | Emit the approved event taxonomy; strip identifiers and behavioural events in child mode; record failure reasons coarsely; record Phase 0 metrics row-by-row at release. | Duplicate receipt data into analytics; emit sensitive cultural or child-identifying payloads; release without Phase 0 evidence. | FEAT-OBS-001 to FEAT-OBS-003, FEAT-REL-001, /spec/13-observability/, /spec/17-phases/. |
7.3 — State transitions
7.3.1 — User and onboarding state
stateDiagram-v2
[*] --> FirstLaunch
FirstLaunch --> AnonymousSessionCreated: auth.signInAnonymously succeeds
AnonymousSessionCreated --> OnboardingInProgress: profile row exists
OnboardingInProgress --> PreferencesCaptured: themes + audience + accessibility saved
PreferencesCaptured --> LibraryRevealed: starter path available
LibraryRevealed --> FirstPlayStarted: user opens starter artwork
FirstPlayStarted --> AhaMomentReached: first ten cells filled on starter artwork
AhaMomentReached --> FounderNoteEligible: completion or qualifying milestone
FounderNoteEligible --> AccountPromptEligible: note dismissed or completed
AccountPromptEligible --> AnonymousContinuing: prompt dismissed
AccountPromptEligible --> Authenticated: account upgraded
AnonymousContinuing --> Authenticated: later sign-in or purchase path
The transition table documents the key transitions in the diagram. The diagram is the canonical state list; transitions not tabulated below follow the same general pattern (user input drives state, error surfaces inline, no progress lost).
| Transition | Input | System response | Error response |
|---|---|---|---|
| First launch to anonymous session | App open with no stored auth token. | Create anonymous session, create profiles row, initialise local database. | Retry auth; if still unavailable, show recoverable startup error and do not show catalogue. |
| Preferences captured | Theme, audience, accessibility selections. At least one cultural theme must be selected. | Persist to profiles and local cache; update library ranking inputs. | Keep user on current step with field-level recovery; do not drop previous selections; block the “continue” affordance until at least one theme is selected. |
| Aha moment reached | Tenth correct region fill on starter artwork (/spec/03-glossary/ §3.4 Aha moment). | Emit allowed activation event if policy permits; fire FEAT-PROG-004 soft account-prompt trigger; record activation timer for /prd/06-prd-v1/ §6.7. | If local write fails, block further progress writes and surface a storage error; do not fire the trigger from a failed write. |
| Account upgrade | User accepts account prompt or purchase requires sign-in. | Promote anonymous account or merge into existing account; return user to prior task. | Preserve anonymous local state; show recoverable auth failure. |
7.3.2 — Artwork access and download state
stateDiagram-v2
[*] --> CatalogueVisible
CatalogueVisible --> DetailViewed: user opens artwork
DetailViewed --> DownloadRequested: free or entitled artwork
DetailViewed --> PaywallRequired: locked premium artwork
PaywallRequired --> AccountRequired: user is anonymous
AccountRequired --> PaywallRequired: sign-in succeeds
PaywallRequired --> Entitled: purchase or restore succeeds
Entitled --> DownloadRequested
DownloadRequested --> Downloading: URL response received
Downloading --> Verifying: all files downloaded
Verifying --> CachedPlayable: checksum and manifest valid
Verifying --> DownloadFailed: checksum failure after retry
CachedPlayable --> OfflinePlayable: network unavailable
CachedPlayable --> VersionReview: newer bundle detected
VersionReview --> CachedPlayable: compatible mapping
VersionReview --> OldVersionPlayable: incompatible mapping
As with §7.3.1, the table documents the key states; the diagram above is the canonical list. States not tabulated (DetailViewed, AccountRequired, Entitled, DownloadFailed, OfflinePlayable, VersionReview) follow ordinary “enter on user action / exit on next action” semantics; recovery paths for failures are tabulated in §7.5.
| State | Entry condition | Exit condition | Required behaviour |
|---|---|---|---|
PaywallRequired | Premium artwork is not covered by an active entitlement. | Purchase, restore, or dismissal. | Anonymous users route through account upgrade before native purchase. |
Downloading | Download URL response has been accepted. | All files received or retry budget exhausted. | Use resumable transfer; renew signed URLs after expiry; write only to temp path. |
Verifying | Downloaded files are present in temp path. | Checksum and manifest pass or fail. | Decompress regions.bin.br, verify SHA-256, and promote atomically only after success. |
CachedPlayable | Current pointer references a verified bundle. | User opens canvas, cache pressure evicts eligible item, or version review starts. | Opening cached artwork cannot require a network round-trip. |
OldVersionPlayable | New bundle cannot map existing progress safely. | User restarts on new version or old version is retired at next launch. | Do not corrupt existing progress; make the choice explicit. |
7.3.3 — Canvas and progress state
stateDiagram-v2
[*] --> ArtworkLoaded
ArtworkLoaded --> ColourSelected: user selects palette swatch
ColourSelected --> TapReceived: user taps canvas
TapReceived --> NoHit: no candidate region
TapReceived --> WrongColour: candidate region colour differs
TapReceived --> CorrectHit: candidate region colour matches
NoHit --> ColourSelected: user retries
WrongColour --> ColourSelected: gentle feedback complete
CorrectHit --> LocalProgressWritten: bitset updated
LocalProgressWritten --> SyncQueued: local write succeeds
SyncQueued --> Completed: completed_count == region_count
SyncQueued --> ColourSelected: continue colouring
Completed --> FounderNoteEligible
| Input | Behaviour | Output |
|---|---|---|
| Palette swatch selected | Set last_selected_colour_id; update selected visual and semantics. | Palette selected state; optional matching-region highlight action becomes available. |
| Canvas tap | Convert screen position through inverse transform, query spatial grid, bounds reject, then precise path containment. | No-hit, wrong-colour feedback, or correct fill. |
| Correct fill | Set region bit, increment count, update percentage, schedule repaint, persist local row. | Local progress row updated, sync job queued, analytics event emitted if policy permits. |
| Wrong colour | Do not change progress; pulse correct swatch or region for 80 ms; optional haptic if OS permits. | Calm feedback only. |
| No hit | No candidate region under the tap (e.g. tap on the background or between regions). | No state change; ignore the tap with no feedback, or apply snap-to-nearest small region per FEAT-ACC-003 if within the snap radius. |
| Completion | Detect completed_count == region_count; set completed_at; trigger completion state. | Library/detail update, founder note eligibility, completion event if policy permits. |
7.3.4 — Publication state
stateDiagram-v2
[*] --> Draft
Draft --> Generated: bundle generator succeeds
Generated --> ValidationFailed: validator error
ValidationFailed --> Generated: artist or operator fixes bundle
Generated --> Validated: validator passes
Validated --> ReviewRequested
ReviewRequested --> ChangesRequested: reviewer rejects
ChangesRequested --> Generated: content revised
ReviewRequested --> Approved: reviewer approves
Approved --> Uploaded: storage upload succeeds
Uploaded --> Previewed: internal preview passes
Previewed --> Published: admin publish function succeeds
Published --> Unpublished: admin unpublish function succeeds
Unpublished --> Published: admin re-publish function succeeds (review status still approved)
Unpublished --> Generated: artwork returns to production for material revision
Publication cannot skip Validated or Approved. Warnings may proceed only with recorded sign-off; errors block publish. Re-publishing an unpublished artwork is allowed if its review status is still approved and the bundle checksum still matches; a material revision sends the artwork back through Generated → Validated → ReviewRequested before it can publish again.
7.4 — Inputs and outputs by module
Every module named in §7.2 has a row below. Cross-cutting concerns (banned UI conventions, child-mode policy) apply to all rows and are not repeated here.
| Module | Inputs | Outputs | Persistence |
|---|---|---|---|
| Anonymous identity | Stored auth token (none on first launch), OS auth state, optional sign-in input. | Anonymous JWT, profile row, merged progress on account upgrade. | flutter_secure_storage token cache, profiles row. |
| Onboarding and retention | OS reduce-motion state, user selections, anonymous profile, completion signals for retention checklist. | Profile preferences, library ranking inputs, first-play route, retention checklist progress. | profiles.cultural_themes, profiles.audience, profiles.child_mode, profiles.accessibility, local checklist dismissal state. |
| Trust moment | Aha-moment trigger and completion event from Progress module, founder’s-note copy (OD-10). | Founder’s note presentation, soft account prompt invocation. | Local “founder’s note seen” flag, soft-account-prompt dismissal state. |
| Notifications | Pre-permission opt-in state, profile cultural themes, OS notification permission, pre-permission copy (OD-12). | OS notification permission request (only after in-app opt-in), notification routing to artwork or pack detail. | Notification preference flag in profiles, OS-side permission state (read-only to the app). |
| Library | Catalogue rows, local cache index, local progress rows, profile preferences. | Filtered/ranked artwork lists, continue row, downloaded row, empty/offline states. | Local catalogue snapshot and cache metadata. |
| Artwork detail | Artwork row, entitlement state, local progress, cache state. | Primary action state, metadata view, report/support link. | No new durable state unless action starts download or purchase. |
| Download/cache | Download URL response, HTTP bytes, manifest, checksum. | Verified bundle, cache pointer, download analytics, error state. | App-support bundle directory, verified_at, current pointer, cache index. |
| Canvas | Verified bundle, progress bitset, palette, accessibility settings. | Filled regions, feedback, progress updates, completion state. | Local progress row, sync queue entry. |
| Palette | Artwork palette from manifest, selected colour ID, remaining counts from Progress. | Palette UI state (selected swatch, completed dim/move), highlight-remaining-regions action availability. | Ephemeral; selection persists via Progress module’s last_selected_colour_id. |
| Progress | Canvas tap result (correct fill), local bitset, palette selection. | Updated bitset, completion percentage, sync queue entry, aha-moment trigger, completion event. | Local progress row (Drift), sync queue; server user_artwork_progress via sync-progress. |
| Purchase | Product ID, platform receipt, user identity, store response. | Receipt validation request, entitlement row, purchase analytics. | purchase_receipts, entitlements, secure receipt cache. |
| Settings | User profile, OS state (reduce motion, notification permission), user-initiated actions, restore trigger. | Updated preferences, child-mode policy application, restore invocation, support/reporting outbound links. | profiles row updates, secure receipt cache (during restore). |
| Content pipeline | Source artwork, segmentation output, metadata, reviewer decision. | Bundle, validator report, review row, storage object, published catalogue row. | Storage bundle, artworks, moderation_reviews, related taxonomy tables. |
| Observability and release | App lifecycle, user actions, failures, performance timers, Phase 0 measurement output. | Product events, crash reports, performance traces, release-gate record. | PostHog event store, Sentry, InsForge function logs, release-build artefact metadata. |
7.5 — Edge cases and error handling
| Case | Trigger | User-facing response | System response | Traceability |
|---|---|---|---|---|
| Anonymous premium request | Anonymous user taps locked premium artwork. | Explain sign-in is required before purchase; return to paywall after upgrade. | Do not request signed premium URLs until authenticated entitlement exists. | JRN-F01, FEAT-DL-001, FEAT-ID-002. |
| No entitlement | Signed-in user opens locked premium artwork. | Show content-pack paywall with restore option. | Return 402 paywall from download URL function. | JRN-F02, ADR-007. |
| Receipt validation failure | Store purchase completes but backend cannot validate. | Keep artwork locked; show retry or restore path. | Persist failed validation audit where applicable; emit coarse purchase_failed. | JRN-F03, FEAT-IAP-003. |
| Checksum mismatch | Downloaded bundle fails integrity check. | Retry once, then show recoverable download error. | Delete partial files; log failure to Sentry. | JRN-F04, /spec/06-data-model/ §6.6. |
| Signed URL expiry | Premium download continues after URL expiry. | Keep progress indicator active where possible. | Request fresh URL and resume with range request. | JRN-F05, /spec/08-api/ §8.2. |
| Offline catalogue refresh | App opens without connectivity. | Show cached catalogue and downloaded artwork; explain refresh limitation only where needed. | Do not block cached artwork play; queue sync. | JRN-F06, FEAT-NET-001. |
| Progress sync failure | Network or backend rejects sync. | No interruption during colouring. | Preserve local row, queue retry with exponential backoff, emit sync_failed. | JRN-F07, ADR-004. |
| Incompatible artwork version | New bundle cannot safely map old progress. | Offer to continue old version until next launch or restart on new version. | Do not mutate progress until user chooses. | JRN-F08, FEAT-CACHE-002. |
| Validator block | Bundle has invalid geometry, missing assets, or palette failures. | Operator receives actionable errors. | Prevent publish; keep artwork draft. | JRN-F09, FEAT-CONT-003. |
| Child-mode restricted action | Child-mode user taps purchase or external link. | Apply parental gate or safe explanation according to platform policy. | Suppress behavioural analytics and strip identifiers. | JRN-F10, FEAT-SET-003. |
| OS removes cached files | Cache directory is partially missing. | Offer re-download; do not show broken playable state. | Reconcile dangling pointers on launch. | EDGE-004, /spec/06-data-model/ §6.6.6. |
| Very small region tap | User taps near a small target. | Fill the intended region when within snap radius and colour matches. | Apply snap-to-nearest small region logic before failing hit test. | EDGE-005, FEAT-ACC-003. |
7.6 — Data contracts
7.6.1 — Local runtime contracts
| Contract | Required fields | Behavioural rule |
|---|---|---|
| Profile preferences | id, is_anonymous, child_mode, audience, cultural_themes, accessibility. | Local copy may optimise display, but server profile remains authoritative. |
| Artwork manifest | id, slug, title, themes, difficulty, regionCount, paletteSize, premium, version, canvas, files, artist, checksum. | Manifest is read from the verified bundle and must match catalogue identity before opening. Canonical format: /spec/06-data-model/ §6.2 (CLRX v1). |
| Region payload | CLRX v1 header, palette, fixed region index, region data. | Parser supports only declared bundle format range; invalid payload blocks render and triggers recovery. Canonical format: /spec/06-data-model/ §6.2. |
| Cache index | slug, version, current_path, verified_at, last_opened_at, bytes, evictable. | In-progress unsynced artwork is never automatically evicted. |
| Progress row | artwork_id, artwork_version, completed_regions, completed_count, completion_percent, last_selected_colour_id, timestamps. | completed_regions is a bitset; progress is monotonic. |
| Sync queue item | type, artwork_id, payload hash, retry count, next retry time. | Queue retries with exponential backoff and never blocks canvas interaction. |
7.6.2 — API endpoint contracts
| Endpoint | Called by | Spec ref | Input | Success output | Error output |
|---|---|---|---|---|---|
GET /artworks | Library | /spec/08-api/ §8.1 | JWT-authenticated read request and query filters. | Published artwork rows filtered by RLS. | Auth/session error; empty published result set. |
GET /artworks/{slug} | Artwork detail | /spec/08-api/ §8.1 | slug. | Published artwork detail row; draft rows only for permitted roles. | Not found or filtered by RLS. |
GET /artwork_categories | Library filters | /spec/08-api/ §8.1 | JWT-authenticated read request. | Category rows. | Auth/session error. |
GET /content_packs | Paywall/library | /spec/08-api/ §8.1 | JWT-authenticated read request. | Published pack rows and ownership context where available. | Auth/session error. |
GET /content_packs/{slug} | Pack detail/paywall | /spec/08-api/ §8.1 | slug. | Pack detail and artwork membership. | Not found or filtered by RLS. |
POST /functions/get-artwork-download-url | Download module | /spec/08-api/ §8.2 | { "slug": "..." }. | { kind: "public", ...urls } for free artwork or { kind: "signed", ...urls, expiresAt } for entitled premium artwork. | 403 sign_in_required, 402 paywall, 404 not_found, rate-limit error. |
GET /user_artwork_progress | Progress module | /spec/08-api/ §8.3 | User JWT and optional artwork filter. | User-owned progress rows only. | Auth/session error or RLS denial. |
POST /functions/sync-progress | Sync queue | /spec/08-api/ §8.3 | artworkId, artworkVersion, completedRegions, completedCount, lastSelectedColourId, lastPlayedAt. | Merged progress row after bitset union. | Validation error, version mismatch, retryable backend error. |
POST /functions/validate-purchase | Purchase module | /spec/08-api/ §8.4 | Platform, product ID, receipt/transaction token. | Active entitlement and receipt audit record. | Invalid receipt, store unavailable, product mismatch, retryable backend error. |
GET /entitlements | Paywall, detail, restore | /spec/08-api/ §8.4 | User JWT. | Active user entitlements. | Auth/session error. |
POST /functions/restore-purchases | Paywall/settings | /spec/08-api/ §8.4 | Platform restore payload. | Reconciled entitlements. | Anonymous user, no purchases, store unavailable. |
POST /functions/store-notification | Store webhook | /spec/08-api/ §8.4 | Apple ASSN v2 or Google RTDN payload. | Receipt/entitlement state updated. | Signature or payload validation failure. |
POST /functions/admin-* | Admin tooling | /spec/08-api/ §8.5 | Admin JWT and function-specific payload. | Draft, upload URL, review request, publish, or unpublish result. | Role failure, validation error, review not approved, missing bundle. |
7.6.3 — CLI and tooling command contracts
The exact executable name can change during implementation. oands below is a placeholder name for the Ochre & Soul authoring CLI; the final tooling name is TBD. The behavioural contract is binding for v1 tooling; any alternative command surface must provide the same inputs, outputs, and failure semantics.
| Command | Purpose | Required input | Required output | Failure behaviour |
|---|---|---|---|---|
oands bundle generate | Convert authored vector/segmentation sources into a CLRX v1 bundle. | Source vector file, metadata file, palette file, output directory. | manifest.json, regions.bin.br, preview.webp, thumbnail.webp, optional line_art.svg, version.txt. | Exit non-zero with actionable error; do not write a partial final bundle. |
oands bundle validate | Validate bundle structure, geometry, palette, accessibility, and required metadata. | Bundle directory. | Machine-readable report with error, warn, and pass entries. | Any error blocks publish; warn requires recorded sign-off. |
oands artwork upload | Upload a validated bundle to storage using admin-generated URLs. | Bundle directory, artwork slug, admin token or session. | Uploaded storage object paths and checksum confirmation. | Abort on failed upload; never expose service-role key. |
oands artwork preview | Open or generate an internal preview for reviewer/admin inspection. | Artwork slug or local bundle path. | Preview URL or local preview artefact. | Refuse preview if validator has blocking errors. |
oands artwork request-review | Move a validated draft into cultural review. | Artwork slug, reviewer target, validator report. | Review request record and status. | Refuse when validator errors remain. |
oands artwork publish | Publish approved artwork to the catalogue. | Artwork slug, approved review ID, bundle version. | Published catalogue row and public visibility confirmation. | Refuse if review is missing, not approved, or bundle checksum mismatches. |
oands artwork unpublish | Remove artwork from the published catalogue. | Artwork slug, reason. | is_published = false confirmation. | Record failure reason; do not delete storage objects automatically. |
7.7 — Event schemas
All events are suppressed in child mode except app_opened and crash signals. Event payloads must avoid sensitive cultural notes, raw receipt data, child identifiers, and free-text user input.
| Event | Required properties | Emitted when | Notes |
|---|---|---|---|
app_opened | { session_id, app_version, child_mode } | App foregrounds or cold starts. | Allowed in child mode with identifiers stripped. |
library_viewed | { section } | User views a library section. | section is featured, new, category, or downloaded. |
artwork_viewed | { artwork_id, source } | Artwork detail opens. | source is library, continue row, notification, or internal preview where applicable. |
artwork_download_started | { artwork_id, premium } | Download begins. | Do not include signed URLs. |
artwork_download_completed | { artwork_id, bytes, duration_ms } | Verified bundle is promoted to cache. | Emit only after checksum success. |
artwork_opened | { artwork_id, open_duration_ms } | Canvas first paint completes. | Used for performance monitoring. |
region_filled | { artwork_id, colour_id, correct } | Region tap is processed. | Consider sampling if event volume is high; suppressed in child mode. |
artwork_completed | { artwork_id, total_duration_min } | Completion reaches 100%. | No artwork title or cultural notes in payload. |
paywall_viewed | { trigger } | Paywall opens. | trigger should be coarse, such as locked_artwork or restore. |
purchase_started | { product_id } | Native purchase flow starts. | No price or receipt payload required. |
purchase_succeeded | { product_id } | Backend validation grants entitlement. | Emit after server validation, not store sheet success alone. |
purchase_failed | { product_id, reason } | Purchase or validation fails. | reason is coarse: cancelled, invalid_receipt, store_unavailable, network, unknown. |
sync_failed | { reason } | Progress sync fails after an attempt. | reason is coarse and non-sensitive. |
7.8 — Traceability matrix
Every row names all FEAT IDs in scope — user-facing and supporting infrastructure. Together the rows cover the 67 frozen records (/prd/05-feature-freeze/ §5.3).
| Functional area | PRD v1 requirement | Feature IDs | Journeys | Architecture/spec references |
|---|---|---|---|---|
| Anonymous-first identity | /prd/06-prd-v1/ §6.4 Identity. | FEAT-ID-001 to FEAT-ID-003, FEAT-DATA-001, FEAT-API-003. | JRN-P01, JRN-A08, EDGE-006. | ADR-005, /spec/07-data-layer/ §7.8. |
| Onboarding and retention | §6.4 Onboarding and retention. | FEAT-ONB-001 to FEAT-ONB-006, FEAT-RET-001. | JRN-P01, EDGE-001, EDGE-003. | /spec/09-user-flows/ §9.7, /spec/22-principles/ principle 6. |
| Trust moment and notifications | §6.4 Trust moment, Notifications. | FEAT-ONB-007, FEAT-ONB-008, FEAT-ONB-009, FEAT-NOT-001, FEAT-PROG-003, FEAT-PROG-004, FEAT-OPEN-001, FEAT-OPEN-003. | JRN-P01, JRN-A08, EDGE-006. | /spec/09-user-flows/ §9.7, /spec/20-open/ OD-07, OD-10, OD-12. |
| Library and artwork decisioning | §6.4 Library, Artwork detail. | FEAT-LIB-001 to FEAT-LIB-004, FEAT-ART-001, FEAT-ART-002, FEAT-DATA-002, FEAT-API-001. | JRN-P02, JRN-P03, JRN-P04, JRN-F06, EDGE-008. | /spec/04-features/ §4.1–§4.2. |
| Offline download and cache | §6.4 Download and cache; §6.5 Offline play. | FEAT-DL-001, FEAT-DL-002, FEAT-CACHE-001, FEAT-CACHE-002, FEAT-NET-001, FEAT-DATA-003. | JRN-P03, JRN-A06, JRN-F04, JRN-F05, JRN-F08, EDGE-004, EDGE-007. | ADR-001, ADR-007, ADR-011, /spec/06-data-model/ §6.2, §6.6. |
| Canvas, palette, accessibility | §6.4 Canvas and palette, Accessibility. | FEAT-CAN-001 to FEAT-CAN-004, FEAT-PAL-001, FEAT-PAL-002, FEAT-ACC-001 to FEAT-ACC-003, FEAT-DATA-003. | JRN-P01, JRN-P02, EDGE-003, EDGE-005, EDGE-009. | ADR-003, ADR-010, ADR-012, /spec/11-engineering/, /spec/12-accessibility/. |
| Progress | §6.4 Progress. | FEAT-PROG-001 to FEAT-PROG-003, FEAT-DATA-004, FEAT-API-002. | JRN-P02, JRN-F07. | ADR-004, /spec/07-data-layer/ §7.4. |
| Pack monetisation | §6.4 Monetisation; §6.8 Non-goals. | FEAT-IAP-001 to FEAT-IAP-004, FEAT-DATA-005, FEAT-API-004. | JRN-P04, JRN-A05, JRN-F01 to JRN-F03, EDGE-007. | ADR-007, ADR-008, /spec/04-features/ §4.7. |
| Settings, child mode | §6.4 Settings; §6.5 Privacy and child mode. | FEAT-SET-001 to FEAT-SET-003. | JRN-A02 to JRN-A04, JRN-F10, EDGE-002. | /spec/13-observability/ §13.3. |
| Content pipeline and cultural review | §6.4 Content pipeline; §6.5 Content integrity. | FEAT-CONT-001 to FEAT-CONT-003, FEAT-CULT-001, FEAT-ADMIN-001, FEAT-DATA-006, FEAT-API-005. | JRN-P05, JRN-A07, JRN-F09, EDGE-008, EDGE-009. | ADR-009, ADR-011, /spec/10-content-flows/, /spec/14-culture/. |
| Banned UI conventions | §6.4 cross-cutting; /spec/02-product/ §2.5. | Cross-cutting; constrains every user-facing module above. | All primary journeys. | /spec/02-product/ §2.5. |
| Observability and release | §6.4 Observability and release; §6.7 Success metrics. | FEAT-OBS-001 to FEAT-OBS-003, FEAT-REL-001. | Failure journeys; release gates per §6.6 and §6.10. | /spec/13-observability/, /spec/17-phases/. |
7.9 — Implementation readiness rules
- A module is ready for implementation only when its feature IDs, state transitions, data contracts, and failure responses are represented in this chapter or in a linked spec section.
- A feature is not complete until its success path, at least one recovery path, and its observability requirements are implemented.
- Any behaviour that changes frozen scope, release lane, architecture boundary, or v1 non-goal status requires the Six-Dimension Change Exception process in /prd/05-feature-freeze/ §5.5.