Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
749582f
refactor(commons): extract archive helpers into prisma/lib
omargfh Aug 7, 2026
58519eb
feat(commons): add in-place legacy patch script
omargfh Aug 7, 2026
30a7d31
test(commons): add an end-to-end rehearsal for the legacy patch
omargfh Aug 7, 2026
a32fea4
fix(commons): drop a stale preview when a version is appended
omargfh Aug 7, 2026
79e6310
fix(commons): make version updates and attachment deletes safe to repeat
omargfh Aug 7, 2026
b1c65fd
fix(commons): set the file kind explicitly on migrated attachments
omargfh Aug 10, 2026
1212575
refactor(commons): share one netlogo parser between the archive scripts
omargfh Aug 10, 2026
3116ae0
chore(commons): remove the archive auto-convert script
omargfh Aug 10, 2026
aa7646d
refactor(commons): move the seed fixtures under prisma/seed
omargfh Aug 10, 2026
c86647c
refactor(commons): move the standalone maintenance script under prism…
omargfh Aug 10, 2026
29d1888
refactor(commons): group the legacy migration scripts under prisma/le…
omargfh Aug 10, 2026
1ddc37c
docs(commons): add old schema for reference
omargfh Aug 10, 2026
5bb0134
feat(commons): add collaborator provenance columns
omargfh Aug 10, 2026
7f38834
feat(commons): backfill legacy collaborators
omargfh Aug 10, 2026
3aaaedf
ci(commons): scope staging deployment to staging branch
omargfh Aug 10, 2026
08d01a7
fix(commons): report the interaction counts the import actually wrote
omargfh Aug 11, 2026
3587f8a
perf(commons): skip the unpatchable bulk tables in the diff
omargfh Aug 11, 2026
03ff419
feat(commons): notify legacy users to reset their password
omargfh Aug 11, 2026
46e7d68
feat(commons): step the draft wizard with Next before Publish
omargfh Aug 11, 2026
9347c74
style(commons): revise legacy account notice copy
omargfh Aug 12, 2026
75ba049
style(commons): update copy on reclaim account modal
omargfh Aug 12, 2026
0802c52
ci(commons): add changeSummary to ModelVersion objects for typecheck
omargfh Aug 12, 2026
d017fb4
feat(commons): switch uuid/cuid to nanoid for business logic
omargfh Aug 12, 2026
b90bdfe
fix(commons): stop guessing tag id vs name by shape
omargfh Aug 12, 2026
cb898f9
feat(commons): generate request and correlation ids as nanoids
omargfh Aug 12, 2026
fb7ed19
refactor(commons): emit nanoid-shaped ids from seedId
omargfh Aug 12, 2026
52daaf6
refactor(commons): switch legacy migration row ids to nanoid
omargfh Aug 12, 2026
ec132fd
feat(commons): stop generating and accepting UUID entity ids
omargfh Aug 12, 2026
017ccf7
fix(commons): stop filenameFromKey mangling nanoid-shaped keys
omargfh Aug 12, 2026
7bd8634
test(commons): match nanoid segments in perf timing collector
omargfh Aug 12, 2026
d291b1f
docs(commons): record NanoID id convention, retire UUID from plan docs
omargfh Aug 12, 2026
eabcd9d
refactor(commons): fix rehearsal dump normalisation for nanoid keys
omargfh Aug 12, 2026
29b7763
refactor(commons): rename uuid-named identifiers to id in legacy migr…
omargfh Aug 12, 2026
4da0814
fix(commons): compare preview keys by position, not shape
omargfh Aug 12, 2026
661ed2f
fix(commons): stop autoload registering spec files as plugins
omargfh Aug 13, 2026
e578e1d
fix(commons): register the nanoid format on every ajv instance
omargfh Aug 13, 2026
6707c46
fix(commons): stop cucumber importing vitest specs as support code
omargfh Aug 13, 2026
b7e2758
fix(commons): stop key normalisation eating real filenames
omargfh Aug 13, 2026
cb24cf0
refactor(commons): share the staging key segment length
omargfh Aug 13, 2026
1cd12d3
feat(commons): migrate existing ids and storage keys in one pass
omargfh Aug 13, 2026
06ab506
fix(commons): point the content database at a writable path
omargfh Aug 13, 2026
b8f3f6b
test(commons): cover the content pages in the smoke suite
omargfh Aug 13, 2026
2195ae1
fix(commons): set changeSummary on constructed model versions
omargfh Aug 13, 2026
79f36d7
fix(commons): page tag search by page instead of offset
omargfh Aug 13, 2026
0663a37
feat(commons): replace the tags coming-soon page with a real listing
omargfh Aug 13, 2026
7b2684a
perf(commons): serve the home feed from one cached endpoint
omargfh Aug 13, 2026
ad64495
perf(commons): raise the home feed cache to 45 minutes
omargfh Aug 13, 2026
bcbe05e
perf(commons): fetch recent models separately on a one-minute cache
omargfh Aug 13, 2026
7565599
refactor(commons): mark deferred home sections on the section itself
omargfh Aug 13, 2026
2329085
fix(commons): prepare nuxt before building
omargfh Aug 13, 2026
2dfabd4
Merge branch 'wip/modeling-commons/tags-and-home-cache' into integrat…
omargfh Aug 17, 2026
8ff6797
Merge branch 'wip/modeling-commons/content-pages' into integration/pr…
omargfh Aug 17, 2026
fff1fea
docs(commons): document the legacy patch script
omargfh Aug 7, 2026
1bc5688
docs(commons): record legacy patch decisions
omargfh Aug 7, 2026
81311f8
docs(commons): note the timezone dependency of migrated dob values
omargfh Aug 7, 2026
87a67c3
docs(commons): document the ambiguous-attachment refusal case
omargfh Aug 7, 2026
872112a
chore(commons): regenerate rest client types after integration merge
omargfh Aug 17, 2026
bc8e33f
fix(commons): move dev service volumes off /tmp
omargfh Aug 17, 2026
d96b734
test(commons): record integration verification run
omargfh Aug 17, 2026
88e30f5
feat(commons): add exhaustive read-only sweep harness
omargfh Aug 17, 2026
3d6048b
feat(commons): retire the beta host from build defaults and gate it i…
omargfh Aug 17, 2026
4f05534
fix(commons): read count, not total, when walking paginated collections
omargfh Aug 17, 2026
1c62b57
feat(commons): add non-destructive data-integrity cucumber cohort
omargfh Aug 17, 2026
5a5366c
feat(commons): add resumable promotion orchestrator
omargfh Aug 17, 2026
710ad76
fix(commons): let exported env win over the .env file in promote.sh
omargfh Aug 17, 2026
49a76b8
fix(commons): apply read permissions to the models-by-user listing
omargfh Aug 17, 2026
d406dd9
fix(commons): batch the id-map insert so it survives production scale
omargfh Aug 17, 2026
d67cb29
fix(commons): stream the id-map artifact instead of building one string
omargfh Aug 17, 2026
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
21 changes: 21 additions & 0 deletions .claude/DECISIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Decisions

## Legacy migration — incremental patch (2026-08-07)

`prisma/archive.ts` was a one-shot import and cannot see edits, deletions or new
children of an already-migrated node. `prisma/patch.ts` applies those from a
`diffdb.sh` diff. Full rationale in
`apps/modeling-commons-backend/doc/legacy-migration-patch.md`.

- Reusable logic was extracted from `archive.ts` into `prisma/lib/` rather than
duplicated, so the patch produces byte-identical keys and rows.
- The patch is keyed entirely on `legacyId`; no existing row's `id` is touched.
- Correctness criterion: `archive(baseline) + patch(diff)` must equal
`archive(new snapshot)`. Enforced by `prisma/rehearsal/run.sh`.
- The script refuses to run — rather than guessing — on mid-sequence version
deletes, out-of-order version appends, and in-place attachment edits, because
`ModelVersion` and `ModelAdditionalFile` carry no legacy id.
- `updatedAt` is never patched: Prisma's `@updatedAt` overrode it on create, so
no migrated row ever held the legacy value.
- `ModelInteraction` is out of scope: no legacy id, no unique constraint, and
`archive.ts` migrated zero rows.
9 changes: 9 additions & 0 deletions .github/workflows/test-modeling-commons.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ jobs:
restore-keys: |
node-modules-${{ runner.os }}-

- name: Assert the beta host is gone
run: |
if git grep -In "beta\.modelingcommons" -- \
':!doc/' ':!*/doc/' ':!.ongoing/' ':!*/.ongoing/'; then
echo "::error::The retired beta host appears at the paths above. The app is served from www.modelingcommons.org; only doc/ and .ongoing/ may still mention it."
exit 1
fi

- name: Install dependencies
run: yarn run init
env:
Expand Down Expand Up @@ -154,6 +162,7 @@ jobs:

deploy-staging:
needs: test
if: github.ref == 'refs/heads/staging/modeling-commons'
uses: ./.github/workflows/build-and-push-modeling-commons.yml
with:
environment: modeling-commons-staging
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ GITIGNORE_*/**/*
.env.development
.env.production

apps/modeling-commons-backend/prisma/archive-output
apps/modeling-commons-backend/prisma/avatars
apps/modeling-commons-backend/prisma/legacy-migration/output
apps/modeling-commons-backend/prisma/legacy-migration/avatars
.nuxt
13 changes: 13 additions & 0 deletions apps/modeling-commons-backend/.claude/DECISIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Decisions

## Entity ids: NanoID instead of UUID

All entity ids switched from `crypto.randomUUID()` to NanoID, generated by `newId()` and validated by `idSchema()` in `src/shared/utils/id.ts`.

- 21 characters, default NanoID alphabet `A-Za-z0-9_-`. Collision probability is negligible at this project's scale, and the alphabet is safe unescaped in URL segments, S3 keys, and JSON.
- Hard cutover, no transitional dual-accept window: generation and validation switched together. The project is pre-beta, so a shock is acceptable and a permissive "accept both shapes" period would only leave a pattern lying around that something eventually starts depending on.
- Two deliberate exceptions remain UUID-shaped, each carrying an explaining comment at the source:
- `src/shared/utils/validate-request-id.ts` still accepts inbound UUID `x-correlation-id` / `request-id` headers, for interop with upstream proxies and tracing systems that generate UUIDs.
- `storagePathHash` in `prisma/legacy-migration/lib/file-keys.ts` is a frozen UUID-shaped hash of a legacy integer id, pinned by test. It is deterministic on purpose; changing its output would orphan existing S3 objects.

Full rationale and inventory: `doc/nanoid-id-migration-plan.md`.
7 changes: 7 additions & 0 deletions apps/modeling-commons-backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.ongoing/
prisma/id-migration/output/
reports/sweep-*.json
reports/sweep-summary.md

reports/data-integrity-report.json
reports/data-integrity.html
5 changes: 5 additions & 0 deletions apps/modeling-commons-backend/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ Reference modules: `src/modules/model/` (full shape), `src/modules/event/` (read
- `POST /v1/models/:id/versions` is **multipart/form-data** (required `file` field), not JSON.
- Draft data persists as versioned JSON validated by compiled Typebox `Parse` (`model-draft/schemas/v1.ts`); its `Clean` step strips properties absent from the schema, so add any new draft field to the schema or it's silently dropped on the next read.

## Ids

- All entity ids are NanoIDs generated by `newId()` from `#src/shared/utils/id.ts`. Never generate an id from Node's native crypto random-identifier call directly.
- DTOs validate ids with `idSchema(...)` from the same module, never a hand-written regex or a hardcoded format string for the old identifier shape.

## Routes

- Auth: `preHandler: [requireAuth]` from `#src/shared/hooks/require-auth.ts`.
Expand Down
Loading