Skip to content
Merged
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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,10 @@ fixtures also use the production candidate. These fixtures do not replace a
fresh verified backup of every production database or a scoped rollout and
rollback plan for the shared service.

## Fashion catalog databases

The application bootstraps are scoped to Scraping, the Iceberg catalog and the Vestiaire developer platform. They do not redeploy or change the shared PostgreSQL runtime. Use certificate-verified TLS and protected application credentials. Existing credentials and ownership must be preserved; drift requires separate review.

## Jotwink Backup And Restore

Jotwink has an independent backup service and health timestamp so a failed
Expand Down Expand Up @@ -959,7 +963,7 @@ Jotwink host backup is opt-in through the `jotwink` Compose profile. Provision a
BetaCrew has an independent six-hour backup service for `betacrew` and
`keycloak_betacrew`. Dumps are validated, encrypted with OpenSSL CMS
AES-256-GCM before persistent storage, checksummed, and retained for 35 days.
Provision `/var/lib/makepad/postgres-backups/betacrew` for uid 70 and install
Provision `/var/lib/makepad/postgres-backups/betacrew` for uid 999 and install
the public recipient certificate at
`/etc/makepad/postgres-backup/betacrew-recipient.pem`; keep its private key
offline. Replicate completed backup directories to independently administered
Expand Down
35 changes: 35 additions & 0 deletions bootstrap/vestiaire-developer-platform.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
\set ON_ERROR_STOP on
SELECT pg_advisory_lock(hashtext('makepad-postgres'),hashtext('vestiaire_developer-bootstrap'));
SELECT NOT EXISTS(SELECT 1 FROM pg_roles WHERE rolname='vestiaire_developer_app') AND NOT EXISTS(SELECT 1 FROM pg_database WHERE datname='vestiaire_developer') AS fresh_install \gset
\if :fresh_install
\if :{?vestiaire_developer_app_password}
\else
\echo 'missing vestiaire_developer_app_password'
DO $$ BEGIN RAISE EXCEPTION 'Vestiaire bootstrap precondition failed'; END $$;
\endif
SELECT length(:'vestiaire_developer_app_password') >= 32 AS strong_password \gset
\if :strong_password
\else
\echo 'vestiaire_developer_app_password must contain at least 32 characters'
DO $$ BEGIN RAISE EXCEPTION 'Vestiaire bootstrap precondition failed'; END $$;
\endif
CREATE ROLE vestiaire_developer_app LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS PASSWORD :'vestiaire_developer_app_password';
CREATE DATABASE vestiaire_developer OWNER vestiaire_developer_app;
REVOKE ALL ON DATABASE vestiaire_developer FROM PUBLIC;
GRANT CONNECT ON DATABASE vestiaire_developer TO vestiaire_developer_app;
\else
SELECT EXISTS(
SELECT 1 FROM pg_database d JOIN pg_roles r ON d.datdba=r.oid
WHERE d.datname='vestiaire_developer' AND r.rolname='vestiaire_developer_app'
AND r.rolcanlogin AND NOT r.rolsuper AND NOT r.rolcreatedb
AND NOT r.rolcreaterole AND NOT r.rolreplication AND NOT r.rolbypassrls
AND NOT EXISTS(SELECT 1 FROM pg_auth_members m WHERE m.member=r.oid OR m.roleid=r.oid)
AND NOT EXISTS(SELECT 1 FROM aclexplode(COALESCE(d.datacl,acldefault('d',d.datdba))) a WHERE a.grantee<>d.datdba)
) AS existing_is_scoped \gset
\if :existing_is_scoped
\echo 'Existing Vestiaire ownership and isolation verified; credentials unchanged.'
\else
DO $$ BEGIN RAISE EXCEPTION 'Existing Vestiaire installation is incomplete or unsafe'; END $$;
\endif
\endif
SELECT pg_advisory_unlock(hashtext('makepad-postgres'),hashtext('vestiaire_developer-bootstrap'));