Stored files · per-account folders

CapExpert File Migration

Moving every stored file into a folder of its own account. This site is the plan, the way it was built, and an honest account of how much of it is actually finished — each figure read back out of the live database rather than carried over from the design.

Approach
Same bucketNo new bucket, no rename, nothing deleted
Shape
6 stepsThree gates, each a full stop
Steps complete
2 of 6Steps 1 and 3; two partly done, one unrun, one unbuilt
Values converted
1.49MRe-counted in clone1 on 2026-09-08
Repositories
4Two APIs, web app, thumbnail service
Where this stands

Steps 1 and 2 are done and hold up under measurement. Every file column and JSON key now stores a complete path, and one shared rule builds every new one. Step 5's copier was built by CAP-680 but has never been run — the ledger tables are empty. Step 3 is deployed and running as a Cloud Function. Steps 4 and 6 are not built as the plan describes them.

Two findings are not recorded anywhere else: the copier has no descriptor for 30 of the 73 columns that can hold a path — 51,636 rows, and step 4 shipped without its flag, so the one behaviour change in the plan cannot be reversed without a deploy. Both are set out on CAP-680 Gaps.

The seven pages

7 pages

What we set out to do

The plan

Separate every stored file into a folder of its own account, in the bucket we already have.

  • One bucket, two new top-level trees
  • Records hold the complete path, not a bare name
  • Copy, never move — every original stays
  • Six steps, three gates, each reversible

/plan

Each step and its gate

Step by step

The six steps and three gates in full: what each one does, how it reverses, and where it stands.

  • Steps 1–3 are invisible to users
  • Behaviour changes at step 4
  • Each gate is a full stop, not a checkpoint
  • Nothing is deleted or moved in any step

/structure

How it was built

Execution

The mechanisms that deliver the plan — one path rule, staged uploads, the migrations, the copier.

  • upload-targets.ts as the single path rule
  • Staging in temp/, filed on save
  • 15 migrations applied to clone1
  • Seed → run → write-back, with rollback

/execution

Done vs missing

Validation

The plan measured against the live databases and the three repositories, step by step.

  • 1,488,632 values re-counted in clone1
  • 38 bare names left, all pre-existing
  • capClone is four migrations behind
  • Two steps unbuilt, one gate never run

/validation

What the copier does

CAP-680

The branch that built step 5: the ledger, the runner, the write-back and the admin console.

  • 21 descriptors covering 21 columns
  • Parallel lanes, chained batches, one run flag
  • Rollback is the same SQL reversed
  • 11 endpoints and a 1,570-line console

/cap-680

What it does not do

CAP-680 gaps

The work CAP-680 leaves behind — measured, not guessed.

  • 51,636 rows with no descriptor
  • Eight legacy folders unreachable
  • The queue has never been seeded or run
  • Gate 3 has not been performed

/cap-680-gaps

What is still missing

Remaining

The actionable remainder, ordered by what blocks what.

  • Four steps outstanding, no gate passed
  • capClone is four migrations short
  • Three mis-filing risks before a real run
  • The safeguard that would have caught it all

/remaining