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
64 changes: 64 additions & 0 deletions .github/workflows/application-acl-postgres16-proof.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# SPDX-FileCopyrightText: 2025 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT

name: Application ACL PostgreSQL 16 Proof

on:
pull_request:
branches: [main, dev, develop]
paths:
- ".github/workflows/application-acl-postgres16-proof.yml"
- "docker/application-acl-proof/**"
- "scripts/generate_application_database_acl.py"
- "scripts/ci/prove_application_database_acl.py"
- "src/omnibase_infra/validation/application_database_acl.py"
- "src/omnibase_infra/validation/enums/**"
- "src/omnibase_infra/validation/models/**"
- "src/omnibase_infra/validation/types/**"
- "tests/fixtures/application_database_acl/**"
- "tests/unit/validation/test_application_database_acl.py"
- "tests/ci/test_application_database_acl_contract.py"
- "tests/integration/test_application_acl_postgres16_proof.py"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
rebuilt-postgres16-proof:
name: Rebuilt PostgreSQL 16 ACL and rollback proof
env:
COMPOSE_PROJECT_NAME: application-acl-proof-${{ github.run_id }}-${{ github.run_attempt }}
permissions:
contents: read
runs-on: >-
${{
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.repository)
&& fromJSON(vars.OMNI_PUBLIC_PR_RUNS_ON_JSON || '["ubuntu-latest"]')
|| fromJSON(vars.OMNI_DOCKER_CI_RUNS_ON_JSON || vars.OMNI_TRUSTED_CI_RUNS_ON_JSON || '["self-hosted","omnibase-ci"]')
}}
timeout-minutes: 30

steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Verify Docker engine
run: docker info

- name: Rebuild and prove ACL matrix
run: >-
docker compose
-f docker/application-acl-proof/compose.yml
up --build --abort-on-container-exit --exit-code-from proof

- name: Tear down synthetic proof
if: always()
run: >-
docker compose
-f docker/application-acl-proof/compose.yml
down --volumes --remove-orphans
34 changes: 34 additions & 0 deletions docker/application-acl-proof/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# syntax=docker/dockerfile:1.7
# SPDX-License-Identifier: MIT

ARG UV_VERSION=0.11.8

FROM postgres:16-alpine AS postgres
COPY docker/application-acl-proof/seed.sql /docker-entrypoint-initdb.d/00-acl-seed.sql

FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv-bin

FROM python:3.12-slim AS proof

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PYTHONPATH=/app/src \
UV_PROJECT_ENVIRONMENT=/app/.venv \
UV_HTTP_TIMEOUT=600

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential git libpq-dev postgresql-client \
&& rm -rf /var/lib/apt/lists/*

COPY --from=uv-bin /uv /uvx /usr/local/bin/
WORKDIR /app
COPY pyproject.toml uv.lock README.md LICENSE ./
RUN uv sync --frozen --no-dev --no-install-project

COPY src/ ./src/
COPY tests/fixtures/application_database_acl/ ./proof/fixtures/
COPY scripts/ci/prove_application_database_acl.py ./proof/prove.py
COPY docker/application-acl-proof/generated/prechange-fixture-acl.json ./proof/prechange-fixture-acl.json

CMD ["/app/.venv/bin/python", "/app/proof/prove.py"]
70 changes: 70 additions & 0 deletions docker/application-acl-proof/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Generated application ACL proof

This rebuilt PostgreSQL 16 harness proves the generated one-database ACL and
default-privilege matrix without touching a deployed database. The seed is wholly
synthetic: it contains no dump-derived value, customer identifier, credential, secret,
or live catalog observation.

Run it with rebuilt images:

```bash
docker compose -f docker/application-acl-proof/compose.yml \
up --build --abort-on-container-exit --exit-code-from proof
docker compose -f docker/application-acl-proof/compose.yml \
down --volumes --remove-orphans
```

The same catalog comparator must detect seeded database/schema/object ownership,
`PUBLIC`, broad-object, per-column, grant-option, unsafe-default, PG16 membership,
undeclared-principal, and cross-domain defects before the matrix is
applied. A transient RED control also proves that an undeclared runtime-owned object
cannot hide outside the typed inventory. The harness covers tables, views,
materialized views, sequences, functions, procedures,
enum/domain/composite/range/multirange types, and the `public` schema. It then applies
the generated SQL twice, proves exact catalog
and behavioral access, restores the generated pre-change fixture snapshot including
grantors and membership options, proves a byte-for-byte semantic snapshot match,
reapplies twice, and proves the final state. Routine targets include their PostgreSQL
identity arguments so overloads cannot collapse or receive a name-wide grant.
The generated script has typed `scaffold` and `full` phases. A scaffold can become
`READY` while the full phase remains honestly `BLOCKED` on objects that have not yet
been materialized. Conversely, FULL can be `READY` while SCAFFOLD is `BLOCKED` when
the exact catalog census proves existing roles need attribute hardening; FULL checks
that observed pre-state and repairs it in its transaction, while the additive phase
refuses to conceal it. The scaffold creates absent-but-catalog-proven workload/owner
roles and the three empty target schemas, adds only grants for roles already proven
safe (or newly created safe), and establishes deny-by-default future-object ACLs
only for owner roles it creates.
It preserves existing role attributes, memberships, database ownership, legacy
`CONNECT`, and legacy `public` access; exact revocation and ownership hardening are
FULL-only after the activity/catalog gates pass. A disposable fresh-database lane
proves its wrong-database guard, atomic failure, idempotent apply, legacy
CONNECT/read/write preservation, zero object mutation, hostile collation/type
collision rejection, the later FULL denial, and exact non-cascading removal before
copy. Every script asserts
`current_database()` before its first mutation.

Both phases run through the real `psql` path inside one explicit transaction; an
injected mid-apply error must leave the entire pre-change snapshot unchanged. The
rollback path is independently failure-injected and transactional. It restores
grantor chains topologically for database/schema/object/column ACLs and PG16 role
memberships, then removes only still-empty schemas and dependency-free roles—never
with `CASCADE`. Raw `pg_default_acl` row presence is part of the snapshot: rollback
normalizes PostgreSQL's implicit function/type `PUBLIC` defaults before replaying
captured deviations, and behavioral checks create future objects to prove those
built-ins return. An unrelated-schema default-ACL sentinel remains byte-for-byte and
behaviorally unchanged through scaffold, FULL, and rollback. The same run revokes
all database privileges before re-granting exact
`CONNECT` access and proves positive/negative connection isolation across the eight
approved non-system databases: `omnidash_analytics`, `omninode_cloud`, `keycloak`,
`omnibase_infra`, `omniintelligence`, `omniclaude`, `omnimemory`, and `umami`.

`generated/prechange-fixture-acl.json` is explicitly a sanitized fixture rollback
artifact, not a live RDS ACL capture or a full-day `(datname, usename)` sample. The
locked real-source candidate remains `BLOCKED` and emits no production SQL until an
authorized exact principal census (including explicit cluster-global presence and
absence evidence), immutable source-locked catalog/activity query and result blobs,
a complete 24-hour-or-longer activity window, an
independent typed principal/domain policy, exact function signatures and object-kind
counts, materialized target-location evidence (source and target may coexist), and
the named catalog/activity/ownership blockers are resolved.
30 changes: 30 additions & 0 deletions docker/application-acl-proof/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SPDX-License-Identifier: MIT
services:
postgres:
build:
context: ../..
dockerfile: docker/application-acl-proof/Dockerfile
target: postgres
environment:
POSTGRES_DB: omnidash_analytics
POSTGRES_PASSWORD: acl-proof-admin-only # pragma: allowlist secret
tmpfs:
- /var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d omnidash_analytics"]
interval: 1s
timeout: 3s
retries: 30
proof:
build:
context: ../..
dockerfile: docker/application-acl-proof/Dockerfile
target: proof
depends_on:
postgres:
condition: service_healthy
environment:
ADMIN_DSN: postgresql://postgres:acl-proof-admin-only@postgres:5432/omnidash_analytics # pragma: allowlist secret
UPDATE_PRECHANGE: ${UPDATE_PRECHANGE:-false}
volumes:
- ./generated:/output
Loading
Loading