Product Requirements
Section 07

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 itemIncluded in this chapterSource of truth
Functional modulesApp, backend, and content-pipeline modules required for v1.This chapter, traced to feature IDs.
Behavioural rulesWhat each module must do, reject, persist, emit, and recover from.This chapter and /prd/02-feature-specification/.
State transitionsUser, artwork, download, purchase, progress, and publication state movement.This chapter, /prd/03-user-journey-flows/, /spec/07-data-layer/.
Data and command contractsAPI endpoints, local data contracts, CLI/tooling commands, and event schemas./spec/06-data-model/, /spec/08-api/, /spec/13-observability/, this chapter.
Error handlingRecoverable 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.

ModuleOwnsMust doMust not doTraceability
Anonymous identityFirst-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 retentionWelcome, 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 momentThe 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.
NotificationsOpt-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.
LibraryPublished 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 detailArtwork 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 cacheDownload 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 engineRendering, 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.
PaletteNumbered 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.
ProgressLocal 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.
MonetisationPack 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.
SettingsAccount, 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 pipelineAuthoring, 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 releaseProduct 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).

TransitionInputSystem responseError response
First launch to anonymous sessionApp 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 capturedTheme, 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 reachedTenth 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 upgradeUser 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.

StateEntry conditionExit conditionRequired behaviour
PaywallRequiredPremium artwork is not covered by an active entitlement.Purchase, restore, or dismissal.Anonymous users route through account upgrade before native purchase.
DownloadingDownload 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.
VerifyingDownloaded 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.
CachedPlayableCurrent 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.
OldVersionPlayableNew 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
InputBehaviourOutput
Palette swatch selectedSet last_selected_colour_id; update selected visual and semantics.Palette selected state; optional matching-region highlight action becomes available.
Canvas tapConvert screen position through inverse transform, query spatial grid, bounds reject, then precise path containment.No-hit, wrong-colour feedback, or correct fill.
Correct fillSet 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 colourDo not change progress; pulse correct swatch or region for 80 ms; optional haptic if OS permits.Calm feedback only.
No hitNo 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.
CompletionDetect 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.

ModuleInputsOutputsPersistence
Anonymous identityStored 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 retentionOS 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 momentAha-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.
NotificationsPre-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).
LibraryCatalogue 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 detailArtwork 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/cacheDownload URL response, HTTP bytes, manifest, checksum.Verified bundle, cache pointer, download analytics, error state.App-support bundle directory, verified_at, current pointer, cache index.
CanvasVerified bundle, progress bitset, palette, accessibility settings.Filled regions, feedback, progress updates, completion state.Local progress row, sync queue entry.
PaletteArtwork 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.
ProgressCanvas 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.
PurchaseProduct ID, platform receipt, user identity, store response.Receipt validation request, entitlement row, purchase analytics.purchase_receipts, entitlements, secure receipt cache.
SettingsUser 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 pipelineSource 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 releaseApp 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

CaseTriggerUser-facing responseSystem responseTraceability
Anonymous premium requestAnonymous 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 entitlementSigned-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 failureStore 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 mismatchDownloaded 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 expiryPremium 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 refreshApp 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 failureNetwork 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 versionNew 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 blockBundle 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 actionChild-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 filesCache 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 tapUser 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

ContractRequired fieldsBehavioural rule
Profile preferencesid, is_anonymous, child_mode, audience, cultural_themes, accessibility.Local copy may optimise display, but server profile remains authoritative.
Artwork manifestid, 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 payloadCLRX 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 indexslug, version, current_path, verified_at, last_opened_at, bytes, evictable.In-progress unsynced artwork is never automatically evicted.
Progress rowartwork_id, artwork_version, completed_regions, completed_count, completion_percent, last_selected_colour_id, timestamps.completed_regions is a bitset; progress is monotonic.
Sync queue itemtype, 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

EndpointCalled bySpec refInputSuccess outputError output
GET /artworksLibrary/spec/08-api/ §8.1JWT-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.1slug.Published artwork detail row; draft rows only for permitted roles.Not found or filtered by RLS.
GET /artwork_categoriesLibrary filters/spec/08-api/ §8.1JWT-authenticated read request.Category rows.Auth/session error.
GET /content_packsPaywall/library/spec/08-api/ §8.1JWT-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.1slug.Pack detail and artwork membership.Not found or filtered by RLS.
POST /functions/get-artwork-download-urlDownload 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_progressProgress module/spec/08-api/ §8.3User JWT and optional artwork filter.User-owned progress rows only.Auth/session error or RLS denial.
POST /functions/sync-progressSync queue/spec/08-api/ §8.3artworkId, artworkVersion, completedRegions, completedCount, lastSelectedColourId, lastPlayedAt.Merged progress row after bitset union.Validation error, version mismatch, retryable backend error.
POST /functions/validate-purchasePurchase module/spec/08-api/ §8.4Platform, product ID, receipt/transaction token.Active entitlement and receipt audit record.Invalid receipt, store unavailable, product mismatch, retryable backend error.
GET /entitlementsPaywall, detail, restore/spec/08-api/ §8.4User JWT.Active user entitlements.Auth/session error.
POST /functions/restore-purchasesPaywall/settings/spec/08-api/ §8.4Platform restore payload.Reconciled entitlements.Anonymous user, no purchases, store unavailable.
POST /functions/store-notificationStore webhook/spec/08-api/ §8.4Apple ASSN v2 or Google RTDN payload.Receipt/entitlement state updated.Signature or payload validation failure.
POST /functions/admin-*Admin tooling/spec/08-api/ §8.5Admin 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.

CommandPurposeRequired inputRequired outputFailure behaviour
oands bundle generateConvert 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 validateValidate 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 uploadUpload 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 previewOpen 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-reviewMove a validated draft into cultural review.Artwork slug, reviewer target, validator report.Review request record and status.Refuse when validator errors remain.
oands artwork publishPublish 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 unpublishRemove 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.

EventRequired propertiesEmitted whenNotes
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 areaPRD v1 requirementFeature IDsJourneysArchitecture/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.