Skip to content
Open
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
1 change: 1 addition & 0 deletions docs/dev/catalog-import-gaps.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ Unlike `docs/progress/` entries (frozen ADR snapshots), this file is **mutable b
- **What breaks:** install never completes. No malmo-assignable UID can write the 1001-owned baked dir — verified that **root under `cap_drop: ALL` also can't** (no `CAP_DAC_OVERRIDE`); only uid 1001 works. Separately, the bundled Postgres can't chown its datadir as root under the stripped `CAP_CHOWN`.
- **Why malmo can't satisfy it (v1):** `writeOverride` pins one malmo-owned `user:` + `cap_drop: ALL` + `no-new-privileges` on **every** service (`internal/lifecycle/lifecycle.go`), and admission rejects a numeric `user:` (`internal/admission/admission.go`) — by design, since a manifest-named UID would alias a real host principal under malmo's no-userns-remap model (`APP_ISOLATION.md` # Runtime identity & data ownership, `THREAT_MODEL.md`). The main app hardcodes an internal UID for its own baked files and ignores the runtime `user:` — the **same hardcoded-internal-UID class as poznote/postiz**, which waits on userns-remap. The "conflicting per-service-UID" framing (#193 case 2) adds no separate need: the Postgres sidecar adopts any non-root UID fine via `service_user: true` (the runtime `user:` malmo would pin), so the only service that truly blocks is the main app's hardcoded 1001 — still case 1. Per-service distinct UIDs wouldn't help.
- **Status:** open — curation-reject, no `catalog/formbricks/` files written. Platform limitation triaged on **#193** (filed off #182). Same fate as poznote/postiz; deferred to `NEXT.md` # User-namespace remap for hardcoded-internal-UID app images (the count-trigger is now met, but the mechanism stays gated on the feasibility spike there). The four Gate-D *degradations* recorded in #182 (link-survey reachability, OAuth callbacks, SMTP, third-party integrations) are independent of this gap and don't apply — the app never reaches a degraded-but-running state.
- **Re-confirmed live (2026-06-30) — shadow-bind workaround is structurally impossible, don't re-attempt:** a later session revived #182 with a drafted entry that split migrations into a one-shot `formbricks-migrate` service (`SKIP_STARTUP_MIGRATION=true` on the app) and **shadow-mounted** a writable bind (`./data/db-migrations-staging`, chowned to the runtime UID) over `/home/nextjs/packages/database/migrations`, betting that gives the runner a writable dir. Booted under the real override (non-1001 `user:`, `cap_drop: ALL`, `no-new-privileges`, binds chowned to the runtime UID): `pgvector/pgvector:pg18` Postgres and `valkey` both come up **healthy**, but `formbricks-migrate` exits 1 with `EACCES: permission denied, rmdir '/home/nextjs/packages/database/migrations'`. The runner doesn't write *into* that dir — `runMigrations` (`packages/database/src/scripts/migration-runner.ts`) `fs.rm`s the dir **itself** then `fs.mkdir`s it on every run, and the path is hardcoded (`PRISMA_MIGRATIONS_DIR = path.resolve(__dirname, "../../migrations")`, **no env override**). `rmdir` of the dir (or of the bind's mountpoint) needs write on the **1001-owned parent** `/home/nextjs/packages/database/`, which no malmo-assigned UID has; the parent can't be shadowed (it holds the read-only migration source + compiled `dist/`), and the app's own startup-migrate path runs the identical code. So the bind-shadow can never work — this is the same uid-1001 wall, just hit one level up. Still `blocks-start`, still gated on userns-remap; **no `catalog/formbricks/` files shipped.**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Forward-dated re-confirmation timestamp

The new bullet is dated 2026-06-30 but the PR is opened on 2026-06-29. If the live boot was run today, the date should be 2026-06-29 to match the actual event. A one-day discrepancy is harmless in practice, but other entries in this file use the date of the actual run rather than the anticipated merge date, so it's worth aligning.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


### managed-pg-role-creation — windmill (2026-06-25)

Expand Down