This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
-- Gen2 owner-role provisioning for the dedicated bootstrap/migration principal.
|
||||
-- This is intentionally separate from feature migrations and may be run repeatedly.
|
||||
BEGIN;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'world_role') THEN
|
||||
CREATE ROLE world_role LOGIN;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'configuration_role') THEN
|
||||
CREATE ROLE configuration_role LOGIN;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'self_role') THEN
|
||||
CREATE ROLE self_role LOGIN;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
role_name TEXT;
|
||||
can_login BOOLEAN;
|
||||
BEGIN
|
||||
FOREACH role_name IN ARRAY ARRAY['world_role', 'configuration_role', 'self_role'] LOOP
|
||||
SELECT rolcanlogin INTO can_login FROM pg_roles WHERE rolname = role_name;
|
||||
IF can_login IS DISTINCT FROM TRUE THEN
|
||||
RAISE EXCEPTION 'Gen2 owner role % exists but is not a V1-compatible LOGIN role', role_name;
|
||||
END IF;
|
||||
END LOOP;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS world AUTHORIZATION world_role;
|
||||
CREATE SCHEMA IF NOT EXISTS configuration AUTHORIZATION configuration_role;
|
||||
CREATE SCHEMA IF NOT EXISTS self AUTHORIZATION self_role;
|
||||
|
||||
REVOKE ALL ON SCHEMA world, configuration, self FROM PUBLIC;
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
schema_name TEXT;
|
||||
expected_owner TEXT;
|
||||
actual_owner TEXT;
|
||||
BEGIN
|
||||
FOREACH schema_name IN ARRAY ARRAY['world', 'configuration', 'self'] LOOP
|
||||
expected_owner := schema_name || '_role';
|
||||
SELECT pg_get_userbyid(nspowner)
|
||||
INTO actual_owner
|
||||
FROM pg_namespace
|
||||
WHERE nspname = schema_name;
|
||||
IF actual_owner IS DISTINCT FROM expected_owner THEN
|
||||
RAISE EXCEPTION 'Gen2 schema % is owned by %, expected %', schema_name, actual_owner, expected_owner;
|
||||
END IF;
|
||||
END LOOP;
|
||||
END
|
||||
$$;
|
||||
|
||||
COMMIT;
|
||||
@@ -25,6 +25,16 @@ psql_exec() {
|
||||
docker exec -i "$POSTGRES_CONTAINER" psql -v ON_ERROR_STOP=1 -U "$POSTGRES_SUPERUSER" -d "$DATABASE" "$@"
|
||||
}
|
||||
|
||||
# Owner roles and schemas are provisioned by the dedicated bootstrap boundary,
|
||||
# before feature migrations run. This keeps role creation out of migrations and
|
||||
# makes existing PostgreSQL volumes converge idempotently as well.
|
||||
GEN2_BOOTSTRAP="$REPO_DIR/database/bootstrap/002_gen2_roles_and_schemas.sql"
|
||||
if [[ ! -f "$GEN2_BOOTSTRAP" ]]; then
|
||||
echo "migration runner: Gen2 bootstrap is missing" >&2
|
||||
exit 1
|
||||
fi
|
||||
psql_exec < "$GEN2_BOOTSTRAP"
|
||||
|
||||
psql_exec -c "CREATE TABLE IF NOT EXISTS public.assistant_migration_history (migration_id TEXT PRIMARY KEY, applied_at_unix_millis BIGINT NOT NULL CHECK (applied_at_unix_millis > 0));"
|
||||
|
||||
if [[ -n "${MIGRATION_BASELINE:-}" ]]; then
|
||||
|
||||
@@ -4,5 +4,6 @@ LABEL org.opencontainers.image.revision=$SOURCE_REVISION \
|
||||
org.opencontainers.image.source="https://git.cin.su/m/Assistant.git"
|
||||
|
||||
COPY database/bootstrap/001_roles_and_schemas.sql /docker-entrypoint-initdb.d/001_roles_and_schemas.sql
|
||||
COPY database/bootstrap/002_gen2_roles_and_schemas.sql /docker-entrypoint-initdb.d/002_gen2_roles_and_schemas.sql
|
||||
COPY deploy/images/002_owner_passwords.sh /docker-entrypoint-initdb.d/002_owner_passwords.sh
|
||||
RUN chmod 0555 /docker-entrypoint-initdb.d/002_owner_passwords.sh
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"task_file":"dev/tasks/GEN2-027-production-canary-and-controlled-gen2-traffic-transition.json","task_id":"GEN2-027","task_revision":1}
|
||||
{"task_file":"dev/tasks/GEN2-DB-001-provision-gen2-owner-roles.json","task_id":"GEN2-DB-001","task_revision":1}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"task_id": "GEN2-DB-001",
|
||||
"task_revision": 1,
|
||||
"architecture_revision": "ARCH-GEN2-000",
|
||||
"base_repo_revision": "gen2-integration",
|
||||
"risk_tier": "E",
|
||||
"intent": "Исправить provisioning Gen2 owner roles/schemas до применения migrations 046-050 без ослабления V1 DB isolation.",
|
||||
"requirement_ids": ["REQ-GEN2-DB-001-ROLES", "REQ-GEN2-DB-001-OWNERSHIP", "REQ-GEN2-DB-001-IDEMPOTENCY", "REQ-GEN2-DB-001-RECOVERY"],
|
||||
"allowed_change_scope": {
|
||||
"modules": ["database bootstrap", "deployment migration runner"],
|
||||
"paths": [
|
||||
"database/bootstrap/002_gen2_roles_and_schemas.sql",
|
||||
"deploy/apply-migrations.sh",
|
||||
"deploy/images/postgres.Dockerfile",
|
||||
"dev/tasks/GEN2-DB-001-provision-gen2-owner-roles.json",
|
||||
"dev/ACTIVE_TASK.json",
|
||||
"dev/tasks/GEN2-DB-001-provision-gen2-owner-roles.json"
|
||||
],
|
||||
},
|
||||
"forbidden_change_scope": {
|
||||
"paths": [
|
||||
"GEN2-028",
|
||||
"production-canary-before-provisioning",
|
||||
"feature-migration-role-creation",
|
||||
"cross-owner-grants",
|
||||
"new canonical owner",
|
||||
"production canary before provisioning"
|
||||
]
|
||||
},
|
||||
"allowed_architecture_delta": {"new_cross_module_dependencies": 0, "new_canonical_owners": 0, "new_privileges": 0, "new_third_party_dependencies": 0, "new_database_owner_roles": 0},
|
||||
"contracts": {"consume": ["V1 database ownership/ACL", "GEN2 canonical owner registry", "GEN2 execution contract"], "may_change": ["Bootstrap provisioning only; feature migration semantics are unchanged."]},
|
||||
"semantic_owner": "Dedicated PostgreSQL bootstrap/migration principal; semantic ownership remains World, Configuration, SELF and existing V1 owners.",
|
||||
"canonical_state": ["world schema owned by world_role", "configuration schema owned by configuration_role", "self schema owned by self_role", "no cross-owner canonical writes"],
|
||||
"state_transitions": ["missing Gen2 roles/schemas -> idempotently provisioned -> migrations 046-050 apply -> restart/recovery preserves schema and migration state"],
|
||||
"side_effects_and_privileges": ["Create only the three declared LOGIN owner roles when absent.", "Revoke PUBLIC schema privileges and fail closed on an unexpected schema owner.", "Do not invent or print credentials; do not grant cross-owner access."],
|
||||
"persistence_and_migrations": ["Provisioning runs in the dedicated bootstrap boundary before feature migrations.", "Migrations 046-050 remain unchanged and are applied by the existing migration history runner."],
|
||||
"failure_retry_restart": ["Provisioning is safe to run repeatedly.", "Unexpected existing role/schema ownership fails closed and requires an architecture decision.", "PostgreSQL restart/recovery must retain owner roles, schemas, ACL and migration history."],
|
||||
"assumptions": ["This is a user-authorized remediation task for the previously stopped GEN2-027 migration decision.", "No Gen2 runtime consumer currently requires a new database password; credentials are not invented by this task.", "GEN2-027 resumes only after provisioning and recovery evidence; GEN2-028 is not started."],
|
||||
"acceptance_scenarios": ["GEN2-DB-001-SCN-01: all roles required by migrations 046-050 are identified", "GEN2-DB-001-SCN-02: provisioning succeeds twice without duplicate objects", "GEN2-DB-001-SCN-03: migrations 046-050 apply in the controlled deployment path", "GEN2-DB-001-SCN-04: schema owners and PUBLIC ACL are confirmed", "GEN2-DB-001-SCN-05: PostgreSQL restart/recovery preserves the result", "GEN2-DB-001-EXIT: migration blocker is removed without weakening V1 isolation"],
|
||||
"required_tests": ["FAST governance: go run ./cmd/devctl preflight -task dev/tasks/GEN2-DB-001-provision-gen2-owner-roles.json", "FAST scope: go run ./cmd/devctl check-diff -active dev/ACTIVE_TASK.json", "FAST whitespace: git diff --check gen2-integration --", "TARGETED: provisioning repeated twice, migrations 046-050, ACL/ownership verification and PostgreSQL restart/recovery"],
|
||||
"terminal_gap_states": ["BLOCKED_BY_SPEC_GAP", "BLOCKED_BY_ARCHITECTURE_GAP", "BLOCKED_BY_MISSING_CAPABILITY", "BLOCKED_BY_CONFLICT", "REQUIRES_MIGRATION_DECISION"]
|
||||
}
|
||||
Reference in New Issue
Block a user