Skip to content
477 changes: 477 additions & 0 deletions docker/docker-compose.prepr.yml

Large diffs are not rendered by default.

47 changes: 46 additions & 1 deletion scripts/preflight_lane_deploy_attribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,48 @@
#: whose rebuild invalidates the "stability-proven" premise of a live grant.
GRANT_INTERLOCK_LANES: frozenset[str] = frozenset({"stability-test"})

#: The ephemeral pre-PR verify pool (OMN-18893, epic OMN-18888).
#:
#: Spelled as a literal rather than imported from
#: ``scripts/runtime_build/prepr_slot_policy.py``, which is the one declaration
#: of which slots exist. The import would be the tidier expression and it is
#: the wrong trade here: this module is the LIVE attribution gate for the
#: stability lane, and an import across ``scripts/`` into ``scripts/runtime_build/``
#: needs sys.path manipulation at import time, so a syntax error or a missing
#: file in the new pool module would take the stability gate down with it. A
#: new, ephemeral surface must not be able to break an existing governed one.
#:
#: The duplication is pinned instead:
#: ``tests/unit/scripts/test_prepr_verify_lane_entrypoint_omn18893.py`` asserts
#: this set equals ``prepr_slot_policy.POOL_LANE_NAMES``, so adding a slot
#: there and not here is a red test rather than a slot that builds without a
#: stated reason.
#:
#: These lanes are in :data:`REASON_REQUIRED_LANES` and deliberately in NEITHER
#: :data:`GOVERNED_LANES` nor :data:`GRANT_INTERLOCK_LANES`, and the asymmetry
#: is the whole point rather than an oversight:
#:
#: * A slot build is a mutation of a shared host, so it owes a stated reason
#: exactly as a stability rebuild does. That is the OMN-15218 requirement and
#: it is about attribution, not about promotion.
#: * A slot is a premise for NOTHING. It promotes nothing, sources no
#: `stability-proven` digest and never appears in a promotion's evidence
#: chain, so no rebuild of one can erode a live prod grant -- which is the
#: only thing the interlock protects. Extending the interlock here would
#: additionally gate an ordinary branch build on resolving the change-control
#: repository at `@main`, making a pre-PR check fail when a governance
#: surface is unreachable. That is a worse gate than none: it would push
#: branch authors off the sanctioned entrypoint.
#: * GOVERNED_LANES carries promotion-class meaning elsewhere, and
#: tests/unit/scripts/test_prepr_pool_lane_census_omn18890.py asserts the pool
#: stays out of it. Widening that set to get the reason requirement would
#: have silently given a slot stability-class semantics.
POOL_LANES: frozenset[str] = frozenset({"prepr-1", "prepr-2"})

#: Lanes that must declare WHY a deploy is happening. The union, and the set
#: the reason check actually reads.
REASON_REQUIRED_LANES: frozenset[str] = GOVERNED_LANES | POOL_LANES

#: The grant registry path inside the ``onex_change_control`` repo.
GRANTS_REPO_RELPATH = "grants/prod_promotion_grants.yaml"

Expand Down Expand Up @@ -582,7 +624,10 @@ def build_record(
ack = apply_acknowledgement(grant_block, ack_tokens)

refusals: list[str] = []
attribution_required = lane in GOVERNED_LANES
# REASON_REQUIRED_LANES, not GOVERNED_LANES: the pre-PR pool owes a stated
# reason (it mutates a shared host) without being promotion-class (it is a
# premise for nothing). See the constants block for why those are separate.
attribution_required = lane in REASON_REQUIRED_LANES

if attribution_required and not reason:
refusals.append(
Expand Down
58 changes: 54 additions & 4 deletions scripts/provision_db_slot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -316,18 +316,68 @@ PGADMINDB="${POSTGRES_DB:-postgres}"
PGPASSWORD="$POSTGRES_PASSWORD"
export PGPASSWORD

# ---------------------------------------------------------------------------
# HOW psql IS REACHED (OMN-18893)
#
# This script originally invoked a bare `psql`, which assumes a PostgreSQL
# client on the host. The lab host has none -- no binary on PATH, none under
# /usr/lib/postgresql, and no postgresql-client package -- and it never needed
# one, because every migration seam in this repository runs psql INSIDE a
# `postgres:16-alpine` container against the lane's own network. The dev lane's
# forward-migration, cloud-migration, intelligence-migration and migration-gate
# services are all that shape.
#
# Found on the first live slot provisioning: `psql: command not found`, after
# the source snapshot had been staged and the lane lock taken.
#
# So psql is resolved rather than assumed: the host binary when one exists (a
# developer machine, and what the unit tests exercise), otherwise a throwaway
# container on the lane network. Both paths take the password from the
# environment and never from argv, which is why the container form passes a
# bare `-e PGPASSWORD` rather than an inline value -- a value there would be
# visible in `docker inspect` and in the host's process list.
#
# The container path adds no host package and no image pull: postgres:16-alpine
# is already resident, because the dev lane's own migration one-shots run it.
# ---------------------------------------------------------------------------
ONEX_PSQL_IMAGE="${ONEX_PSQL_IMAGE:-postgres:16-alpine}"
ONEX_PSQL_NETWORK="${ONEX_PSQL_NETWORK:-omnibase-infra-network}"

if command -v psql >/dev/null 2>&1; then
ONEX_PSQL_VIA="host-binary"
psql_run() { psql "$@"; }
elif command -v docker >/dev/null 2>&1; then
ONEX_PSQL_VIA="container:${ONEX_PSQL_IMAGE}@${ONEX_PSQL_NETWORK}"
psql_run() {
# -i so a heredoc on stdin reaches psql; --rm so nothing accumulates.
docker run --rm -i --network "$ONEX_PSQL_NETWORK" \
-e PGPASSWORD "$ONEX_PSQL_IMAGE" psql "$@"
}
else
fail "$EXIT_USAGE" \
"no way to reach PostgreSQL: there is no psql on PATH and no docker to
run one in. Slot provisioning refuses rather than guessing, because a
half-provisioned slot on a SHARED server is worse than an unprovisioned
one."
fi

# Printed rather than merely chosen: which path answered is part of the
# provisioning evidence, and a run that silently switched paths between two
# hosts is a difference an operator should be able to see in the log.
echo "[provision-db-slot] psql via ${ONEX_PSQL_VIA}" >&2

psql_admin() {
psql -v ON_ERROR_STOP=1 -X -q -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGADMINDB" "$@"
psql_run -v ON_ERROR_STOP=1 -X -q -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGADMINDB" "$@"
}

psql_admin_in() {
_target_db="$1"
shift
psql -v ON_ERROR_STOP=1 -X -q -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$_target_db" "$@"
psql_run -v ON_ERROR_STOP=1 -X -q -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$_target_db" "$@"
}

scalar() {
psql -X -qAt -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGADMINDB" -c "$1"
psql_run -X -qAt -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGADMINDB" -c "$1"
}

# The whole fence rests on this connection being able to see and refuse
Expand Down Expand Up @@ -382,7 +432,7 @@ database_holds_no_lane_data() {
[ "$_nld_candidate" = "$_nld_db" ] && _nld_listed=1
done
[ "$_nld_listed" -eq 1 ] || return 1
_nld_tables="$(psql -X -qAt -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$_nld_db" \
_nld_tables="$(psql_run -X -qAt -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$_nld_db" \
-c "SELECT count(*) FROM pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema')")"
if [ "$_nld_tables" != "0" ]; then
echo "[provision-db-slot] '${_nld_db}' is listed as holding no lane data but reports ${_nld_tables} application tables — the exemption does not apply" >&2
Expand Down
Loading
Loading