Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions docs_build/database/ddl/sprites.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
-- Game Foundry Studio DEV database DDL
-- Group: Sprites
-- Ownership: docs_build/database/ddl/sprites.sql
-- Target DEV database: gamefoundry_dev
-- Scope: executable grouped table DDL for active Supabase/server API migration.
-- Authoritative key values are generated by the server/API layer.
-- Owned tables: sprite_records, sprite_usage_references
CREATE TABLE IF NOT EXISTS sprite_records (
key text PRIMARY KEY,
"gameId" text REFERENCES game_workspace_games(key),
"ownerUserId" text REFERENCES users(key),
"name" text NOT NULL,
"status" text NOT NULL,
"category" text NOT NULL DEFAULT '',
"tagKeys" jsonb NOT NULL DEFAULT '[]'::jsonb,
"source" text NOT NULL DEFAULT '',
"storageObjectKey" text NOT NULL DEFAULT '',
"storagePath" text NOT NULL DEFAULT '',
"originalName" text NOT NULL DEFAULT '',
"mimeType" text NOT NULL DEFAULT '',
"width" integer,
"height" integer,
"sizeBytes" bigint,
"checksum" text NOT NULL DEFAULT '',
"paletteColorKeys" jsonb NOT NULL DEFAULT '[]'::jsonb,
"archived" boolean NOT NULL DEFAULT false,
"archivedAt" timestamptz,
"createdAt" timestamptz NOT NULL DEFAULT now(),
"updatedAt" timestamptz NOT NULL DEFAULT now(),
"createdBy" text NOT NULL REFERENCES users(key),
"updatedBy" text NOT NULL REFERENCES users(key)
);

CREATE INDEX IF NOT EXISTS idx_sprite_records_gameid ON sprite_records ("gameId");
CREATE INDEX IF NOT EXISTS idx_sprite_records_owneruserid ON sprite_records ("ownerUserId");
CREATE INDEX IF NOT EXISTS idx_sprite_records_status ON sprite_records ("status");
CREATE INDEX IF NOT EXISTS idx_sprite_records_createdby ON sprite_records ("createdBy");
CREATE INDEX IF NOT EXISTS idx_sprite_records_updatedby ON sprite_records ("updatedBy");

CREATE TABLE IF NOT EXISTS sprite_usage_references (
key text PRIMARY KEY,
"spriteKey" text NOT NULL REFERENCES sprite_records(key),
"sourceType" text NOT NULL,
"sourceKey" text NOT NULL,
"label" text NOT NULL DEFAULT '',
"createdAt" timestamptz NOT NULL DEFAULT now(),
"updatedAt" timestamptz NOT NULL DEFAULT now(),
"createdBy" text NOT NULL REFERENCES users(key),
"updatedBy" text NOT NULL REFERENCES users(key)
);

CREATE INDEX IF NOT EXISTS idx_sprite_usage_references_spritekey ON sprite_usage_references ("spriteKey");
CREATE INDEX IF NOT EXISTS idx_sprite_usage_references_source ON sprite_usage_references ("sourceType", "sourceKey");
CREATE INDEX IF NOT EXISTS idx_sprite_usage_references_createdby ON sprite_usage_references ("createdBy");
CREATE INDEX IF NOT EXISTS idx_sprite_usage_references_updatedby ON sprite_usage_references ("updatedBy");
1 change: 1 addition & 0 deletions docs_build/database/dml/DML_INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Direct SQL setup is intentionally narrow. Account DEV users now require server-s
| Objects | `objects.sql` | Server-seed-owned | Server-side seed API |
| Palette | `palette.sql` | Server-seed-owned | Server-side seed API |
| Support Tickets | `support-tickets.sql` | Server-seed-owned | Admin Site Setup/server-side seed API |
| Sprites | `sprites.sql` | Server-seed-owned | Sprites Local API/server-side Postgres service |
| Tags | `tags.sql` | Server-seed-owned | Server-side seed API |
| Tool Metadata | `tool-metadata.sql` | Server-seed-owned | Server-side seed API |
| Tool Planning | `tool-planning.sql` | Server-seed-owned | Server-side seed API |
Expand Down
13 changes: 13 additions & 0 deletions docs_build/database/dml/sprites.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Game Foundry Studio DEV database DML / seed review
-- Group: Sprites
-- Ownership: docs_build/database/dml/sprites.sql
-- Runtime setup/seed operations for this group must run through server-side APIs.
-- Browser pages must not directly seed authoritative DB records.
-- Owned tables: sprite_records, sprite_usage_references

-- DML status: Server-seed-owned.
-- Setup is performed through the Admin-owned server-side seed API and Sprites Local API/server-side Postgres service.
-- Browser pages must not seed authoritative records.
-- The server/API layer generates all non-user keys.
-- This SQL file intentionally has no direct INSERT statements because direct SQL would bypass key/audit ownership.
-- Direct SQL setup for this group remains deferred until a later migration-runner PR explicitly owns it.
5 changes: 4 additions & 1 deletion docs_build/database/seed/guest/sprites.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
"readOnly": true,
"writableByGuest": false,
"signInRedirect": "account/sign-in.html",
"tables": {},
"tables": {
"sprite_records": [],
"sprite_usage_references": []
},
"samplePackages": [
{
"key": "guest-sprites-starter",
Expand Down
13 changes: 13 additions & 0 deletions docs_build/database/seed/sprites.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"group": "Sprites",
"groupKey": "sprites",
"owner": "docs_build/database/seed",
"serverSideSeedRequired": true,
"browserAuthoritativeKeyGenerationAllowed": false,
"colorOwnership": "Palette/Colors owns reusable color definitions; Sprites stores Palette/Colors keys only.",
"tables": {
"sprite_records": [],
"sprite_usage_references": []
},
"note": "Seed records for this group are intentionally empty until a server/API seed path owns them."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# PR_26177_CHARLIE_010-sprites-api-db-foundation

Status: PASS
Team: Charlie
Branch: PR_26177_CHARLIE_010-sprites-api-db-foundation
Date: 2026-06-26
Base branch: main

## Scope

This PR adds the Sprites API and database foundation only. It does not change the Sprites UI and does not implement import, preview, search, reference viewer, or final Playwright polish.

## Implementation Summary

- Added `src/dev-runtime/sprites/sprites-postgres-service.mjs`.
- Exposed shared Local API routes under `/api/sprites/records`.
- Added Postgres DDL/DML/seed artifacts for grouped Sprites ownership.
- Registered Sprites product data tables for provider/product snapshots.
- Added targeted service and Local API contract tests.

## API Contract

The foundation exposes:

- `GET /api/sprites/records`
- `GET /api/sprites/records/:key`
- `POST /api/sprites/records`
- `POST /api/sprites/records/:key`
- `POST /api/sprites/records/:key/archive`
- `POST /api/sprites/records/:key/delete`

Guest browsing is allowed through GET routes. Write routes require a signed-in actor key through the server API session.

## Database Foundation

Grouped database artifacts:

- `docs_build/database/ddl/sprites.sql`
- `docs_build/database/dml/sprites.sql`
- `docs_build/database/seed/sprites.json`
- `docs_build/database/seed/guest/sprites.json`

Owned tables:

- `sprite_records`
- `sprite_usage_references`

`sprite_records` includes server-owned audit fields:

- `key`
- `createdAt`
- `updatedAt`
- `createdBy`
- `updatedBy`

The API/service layer generates record keys and audit values. Browser-created keys are ignored and never trusted as authoritative.

## Palette/Colors Boundary

Sprites does not store reusable color definitions. It stores Palette/Colors references only through `paletteColorKeys`.

The service rejects payload keys that would transfer reusable color ownership into Sprites:

- `colors`
- `hex`
- `palette`
- `paletteColors`
- `swatches`

## Validation Summary

- PASS: `node ./scripts/run-node-test-files.mjs tests/dev-runtime/SpritesPostgresService.test.mjs tests/api/sprites/contract.test.mjs`
- PASS: `git diff --check`
- PASS: no `start_of_day` paths changed.
- PASS: no browser storage SSoT, MEM DB, local-mem, fake-login, imageDataUrl, or silent fallback terms added in Sprites foundation files.
- PASS: no runtime UI changes.
- NOTE: `tests/dev-runtime/SupabaseProductDataCutover.test.mjs` was attempted twice because product table metadata changed. It timed out both times before producing a failure payload, so it is recorded as a non-blocking broader-lane limitation. Required Sprites API/unit validation passed.

## Playwright

Playwright impacted: No. This PR adds API/database foundation only. UI consumption starts in PR_26177_CHARLIE_011.

## ZIP Artifact

`tmp/PR_26177_CHARLIE_010-sprites-api-db-foundation_delta.zip`
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# PR_26177_CHARLIE_010 Branch Validation

Status: PASS
Team: Charlie
Branch: PR_26177_CHARLIE_010-sprites-api-db-foundation
Date: 2026-06-26

| Gate | Result | Evidence |
| --- | --- | --- |
| Started from `main` | PASS | Gate verified before branch creation. |
| Worktree clean before branch | PASS | `git status --short` returned no files before branch creation. |
| Local/origin sync before branch | PASS | `git rev-list --left-right --count main...origin/main` returned `0 0`. |
| One PR purpose | PASS | API/database foundation only. |
| No `start_of_day` changes | PASS | Changed-file check found no `start_of_day` paths. |
| No UI changes | PASS | No HTML/CSS/toolbox UI files changed. |
| Required ZIP exists | PASS | `tmp/PR_26177_CHARLIE_010-sprites-api-db-foundation_delta.zip`. |

## Branch Disposition

Source branch retained for draft PR review.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# PR_26177_CHARLIE_010 Manual Validation Notes

Status: PASS
Team: Charlie
Branch: PR_26177_CHARLIE_010-sprites-api-db-foundation

## Manual Review

- Verified the API foundation is server-side and does not add browser-owned product data.
- Verified the Sprites service generates authoritative ULID keys.
- Verified writes require an authenticated server API session actor.
- Verified reusable colors remain owned by Palette/Colors.
- Verified DML artifacts contain no direct INSERT statements.
- Verified no UI, CSS, HTML, or page-local script behavior changed in this PR.

## Notes For PR_26177_CHARLIE_011

The Sprites UI shell should consume only `/api/sprites/records` and show visible unavailable/error states when the API is unavailable. It should not use page-local product arrays or browser storage as product data.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# PR_26177_CHARLIE_010 Requirements Checklist

Status: PASS
Team: Charlie
Branch: PR_26177_CHARLIE_010-sprites-api-db-foundation

| Requirement | Result | Notes |
| --- | --- | --- |
| Add Sprites API/database foundation | PASS | Added service module and `/api/sprites/records` contract. |
| Add sprite records with audit fields | PASS | `sprite_records` includes key, createdAt, updatedAt, createdBy, updatedBy. |
| API/server owns key generation | PASS | Service generates ULID keys and ignores browser-supplied keys. |
| List/read/create/update/archive/delete contract | PASS | Contract covered in service and API tests. |
| Metadata fields for MVP | PASS | Name, status, category, tags, storage/source, mime, dimensions, size, checksum, and Palette key refs included. |
| Do not store color definitions in Sprites | PASS | Service rejects color definition fields and stores only `paletteColorKeys`. |
| Add DDL/DML/seed files | PASS | Added grouped `sprites` artifacts under `docs_build/database/`. |
| Add targeted API/unit tests | PASS | Added service and `/api/sprites` contract tests. |
| Guest browsing allowed | PASS | GET list route works without session. |
| Guest saving blocked | PASS | POST create returns 401 without signed-in actor. |
| No browser-owned product data | PASS | Browser/UI not changed; API/server owns records. |
| No SQLite direction | PASS | Foundation targets Postgres only. |
| No `start_of_day` changes | PASS | Changed-file check clean. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# PR_26177_CHARLIE_010 Validation Lane

Status: PASS
Team: Charlie
Branch: PR_26177_CHARLIE_010-sprites-api-db-foundation

## Commands

```powershell
node ./scripts/run-node-test-files.mjs tests/dev-runtime/SpritesPostgresService.test.mjs tests/api/sprites/contract.test.mjs
git diff --check
git diff --name-only
git diff --name-only | rg "(^|/)start_of_day(/|$)"
rg -n "MEM DB|local-mem|fake-login|localStorage|sessionStorage|indexedDB|imageDataUrl|silent fallback|Mock DB" src/dev-runtime/sprites tests/dev-runtime/SpritesPostgresService.test.mjs tests/api/sprites/contract.test.mjs docs_build/database/ddl/sprites.sql docs_build/database/dml/sprites.sql docs_build/database/seed/sprites.json
```

## Results

| Validation | Result | Notes |
| --- | --- | --- |
| Sprites service tests | PASS | 4 service tests passed. |
| Sprites Local API contract test | PASS | 1 API contract test passed. |
| `git diff --check` | PASS | No whitespace errors. |
| `start_of_day` check | PASS | No matches. |
| Forbidden runtime term scan | PASS | No forbidden terms found in new Sprites foundation files. |
| Palette/Colors ownership check | PASS | Color definition fields are rejected; `paletteColorKeys` only. |
| Playwright | PASS | Not impacted; no UI changes. |

## Broader Lane Attempt

`node ./scripts/run-node-test-files.mjs tests/dev-runtime/SupabaseProductDataCutover.test.mjs` was attempted twice because product table metadata changed. Both attempts timed out before producing a test failure payload. Required targeted Sprites validation passed.
35 changes: 19 additions & 16 deletions docs_build/dev/reports/codex_changed_files.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
M docs_build/dev/reports/PR_26177_OWNER_057-game-journey-metrics-regression-recovery_branch-validation.md
M docs_build/dev/reports/PR_26177_OWNER_057-game-journey-metrics-regression-recovery_manual-validation-notes.md
M docs_build/dev/reports/PR_26177_OWNER_057-game-journey-metrics-regression-recovery_report.md
M docs_build/dev/reports/PR_26177_OWNER_057-game-journey-metrics-regression-recovery_requirement-checklist.md
M docs_build/dev/reports/PR_26177_OWNER_057-game-journey-metrics-regression-recovery_validation-lane.md
M docs_build/dev/reports/coverage_changed_js_guardrail.txt
M docs_build/dev/reports/playwright_v8_coverage_report.txt
D scripts/migrate-game-journey-completion-metrics-sqlite-to-postgres.mjs
M scripts/validate-browser-env-agnostic.mjs
D src/dev-runtime/persistence/game-journey-completion-metrics-migration.mjs
D tests/dev-runtime/GameJourneyCompletionMetricsMigration.test.mjs
M tests/dev-runtime/GameJourneyCompletionMetricsStore.test.mjs
M tests/playwright/tools/AdminHealthOperationsPage.spec.mjs
M tests/playwright/tools/GameJourneyTool.spec.mjs
M docs_build/dev/reports/codex_changed_files.txt
M docs_build/dev/reports/codex_review.diff
docs_build/database/ddl/sprites.sql
docs_build/database/dml/DML_INDEX.md
docs_build/database/dml/sprites.sql
docs_build/database/seed/guest/sprites.json
docs_build/database/seed/sprites.json
docs_build/dev/reports/PR_26177_CHARLIE_010-sprites-api-db-foundation.md
docs_build/dev/reports/PR_26177_CHARLIE_010-sprites-api-db-foundation_branch-validation.md
docs_build/dev/reports/PR_26177_CHARLIE_010-sprites-api-db-foundation_manual-validation-notes.md
docs_build/dev/reports/PR_26177_CHARLIE_010-sprites-api-db-foundation_requirements-checklist.md
docs_build/dev/reports/PR_26177_CHARLIE_010-sprites-api-db-foundation_validation-lane.md
docs_build/dev/reports/codex_changed_files.txt
docs_build/dev/reports/codex_review.diff
src/dev-runtime/auth/provider-contract-stubs.mjs
src/dev-runtime/persistence/mock-db-store.js
src/dev-runtime/server/local-api-router.mjs
src/dev-runtime/sprites/sprites-postgres-service.mjs
tests/api/sprites/contract.test.mjs
tests/dev-runtime/SpritesPostgresService.test.mjs
tests/helpers/postgresClientStub.mjs
Loading
Loading