Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
mock-dev-release / package-mock-release (push) Has been cancelled
- Added ConsoleExportClient for managing export requests and responses. - Introduced ConsoleExportRequest and ConsoleExportResponse models. - Implemented methods for creating and retrieving exports with appropriate headers. feat(crypto): Add Software SM2/SM3 Cryptography Provider - Implemented SmSoftCryptoProvider for software-only SM2/SM3 cryptography. - Added support for signing and verification using SM2 algorithm. - Included hashing functionality with SM3 algorithm. - Configured options for loading keys from files and environment gate checks. test(crypto): Add unit tests for SmSoftCryptoProvider - Created comprehensive tests for signing, verifying, and hashing functionalities. - Ensured correct behavior for key management and error handling. feat(api): Enhance Console Export Models - Expanded ConsoleExport models to include detailed status and event types. - Added support for various export formats and notification options. test(time): Implement TimeAnchorPolicyService tests - Developed tests for TimeAnchorPolicyService to validate time anchors. - Covered scenarios for anchor validation, drift calculation, and policy enforcement.
326 lines
12 KiB
YAML
326 lines
12 KiB
YAML
# .gitea/workflows/findings-ledger-ci.yml
|
|
# Findings Ledger CI with RLS migration validation (DEVOPS-LEDGER-TEN-48-001-REL)
|
|
|
|
name: Findings Ledger CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'src/Findings/**'
|
|
- '.gitea/workflows/findings-ledger-ci.yml'
|
|
- 'deploy/releases/2025.09-stable.yaml'
|
|
- 'deploy/releases/2025.09-airgap.yaml'
|
|
- 'deploy/downloads/manifest.json'
|
|
- 'ops/devops/release/check_release_manifest.py'
|
|
pull_request:
|
|
branches: [main, develop]
|
|
paths:
|
|
- 'src/Findings/**'
|
|
- '.gitea/workflows/findings-ledger-ci.yml'
|
|
|
|
env:
|
|
DOTNET_VERSION: '10.0.100'
|
|
POSTGRES_IMAGE: postgres:16-alpine
|
|
BUILD_CONFIGURATION: Release
|
|
|
|
jobs:
|
|
build-test:
|
|
runs-on: ubuntu-22.04
|
|
env:
|
|
TEST_RESULTS_DIR: ${{ github.workspace }}/artifacts/test-results
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup .NET ${{ env.DOTNET_VERSION }}
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: ${{ env.DOTNET_VERSION }}
|
|
include-prerelease: true
|
|
|
|
- name: Restore dependencies
|
|
run: |
|
|
dotnet restore src/Findings/StellaOps.Findings.Ledger/StellaOps.Findings.Ledger.csproj
|
|
dotnet restore src/Findings/__Tests/StellaOps.Findings.Ledger.Tests/StellaOps.Findings.Ledger.Tests.csproj
|
|
|
|
- name: Build
|
|
run: |
|
|
dotnet build src/Findings/StellaOps.Findings.Ledger/StellaOps.Findings.Ledger.csproj \
|
|
-c ${{ env.BUILD_CONFIGURATION }} \
|
|
/p:ContinuousIntegrationBuild=true
|
|
|
|
- name: Run unit tests
|
|
run: |
|
|
mkdir -p $TEST_RESULTS_DIR
|
|
dotnet test src/Findings/__Tests/StellaOps.Findings.Ledger.Tests/StellaOps.Findings.Ledger.Tests.csproj \
|
|
-c ${{ env.BUILD_CONFIGURATION }} \
|
|
--logger "trx;LogFileName=ledger-tests.trx" \
|
|
--results-directory $TEST_RESULTS_DIR
|
|
|
|
- name: Upload test results
|
|
uses: actions/upload-artifact@v4
|
|
if: always()
|
|
with:
|
|
name: ledger-test-results
|
|
path: ${{ env.TEST_RESULTS_DIR }}
|
|
|
|
migration-validation:
|
|
runs-on: ubuntu-22.04
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
env:
|
|
POSTGRES_USER: ledgertest
|
|
POSTGRES_PASSWORD: ledgertest
|
|
POSTGRES_DB: ledger_test
|
|
ports:
|
|
- 5432:5432
|
|
options: >-
|
|
--health-cmd pg_isready
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
env:
|
|
PGHOST: localhost
|
|
PGPORT: 5432
|
|
PGUSER: ledgertest
|
|
PGPASSWORD: ledgertest
|
|
PGDATABASE: ledger_test
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET ${{ env.DOTNET_VERSION }}
|
|
uses: actions/setup-dotnet@v4
|
|
with:
|
|
dotnet-version: ${{ env.DOTNET_VERSION }}
|
|
include-prerelease: true
|
|
|
|
- name: Install PostgreSQL client
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y postgresql-client
|
|
|
|
- name: Wait for PostgreSQL
|
|
run: |
|
|
until pg_isready -h $PGHOST -p $PGPORT -U $PGUSER; do
|
|
echo "Waiting for PostgreSQL..."
|
|
sleep 2
|
|
done
|
|
|
|
- name: Apply prerequisite migrations (001-006)
|
|
run: |
|
|
set -euo pipefail
|
|
MIGRATION_DIR="src/Findings/StellaOps.Findings.Ledger/migrations"
|
|
for migration in 001_initial.sql 002_add_evidence_bundle_ref.sql 002_projection_offsets.sql \
|
|
003_policy_rationale.sql 004_ledger_attestations.sql 004_risk_fields.sql \
|
|
005_risk_fields.sql 006_orchestrator_airgap.sql; do
|
|
if [ -f "$MIGRATION_DIR/$migration" ]; then
|
|
echo "Applying migration: $migration"
|
|
psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE -f "$MIGRATION_DIR/$migration"
|
|
fi
|
|
done
|
|
|
|
- name: Apply RLS migration (007_enable_rls.sql)
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Applying RLS migration..."
|
|
psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE \
|
|
-f src/Findings/StellaOps.Findings.Ledger/migrations/007_enable_rls.sql
|
|
|
|
- name: Validate RLS configuration
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Validating RLS is enabled on all protected tables..."
|
|
|
|
# Check RLS enabled
|
|
TABLES_WITH_RLS=$(psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE -t -A -c "
|
|
SELECT COUNT(*)
|
|
FROM pg_class c
|
|
JOIN pg_namespace n ON c.relnamespace = n.oid
|
|
WHERE n.nspname = 'public'
|
|
AND c.relrowsecurity = true
|
|
AND c.relname IN (
|
|
'ledger_events', 'ledger_merkle_roots', 'findings_projection',
|
|
'finding_history', 'triage_actions', 'ledger_attestations',
|
|
'orchestrator_exports', 'airgap_imports'
|
|
);
|
|
")
|
|
|
|
if [ "$TABLES_WITH_RLS" -ne 8 ]; then
|
|
echo "::error::Expected 8 tables with RLS enabled, found $TABLES_WITH_RLS"
|
|
exit 1
|
|
fi
|
|
echo "✓ All 8 tables have RLS enabled"
|
|
|
|
# Check policies exist
|
|
POLICIES=$(psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE -t -A -c "
|
|
SELECT COUNT(DISTINCT tablename)
|
|
FROM pg_policies
|
|
WHERE schemaname = 'public'
|
|
AND policyname LIKE '%_tenant_isolation';
|
|
")
|
|
|
|
if [ "$POLICIES" -ne 8 ]; then
|
|
echo "::error::Expected 8 tenant isolation policies, found $POLICIES"
|
|
exit 1
|
|
fi
|
|
echo "✓ All 8 tenant isolation policies created"
|
|
|
|
# Check tenant function exists
|
|
FUNC_EXISTS=$(psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE -t -A -c "
|
|
SELECT COUNT(*)
|
|
FROM pg_proc p
|
|
JOIN pg_namespace n ON p.pronamespace = n.oid
|
|
WHERE p.proname = 'require_current_tenant'
|
|
AND n.nspname = 'findings_ledger_app';
|
|
")
|
|
|
|
if [ "$FUNC_EXISTS" -ne 1 ]; then
|
|
echo "::error::Tenant function 'require_current_tenant' not found"
|
|
exit 1
|
|
fi
|
|
echo "✓ Tenant function 'findings_ledger_app.require_current_tenant()' exists"
|
|
|
|
echo ""
|
|
echo "=== RLS Migration Validation PASSED ==="
|
|
|
|
- name: Test rollback migration
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Testing rollback migration..."
|
|
psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE \
|
|
-f src/Findings/StellaOps.Findings.Ledger/migrations/007_enable_rls_rollback.sql
|
|
|
|
# Verify RLS is disabled
|
|
TABLES_WITH_RLS=$(psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE -t -A -c "
|
|
SELECT COUNT(*)
|
|
FROM pg_class c
|
|
JOIN pg_namespace n ON c.relnamespace = n.oid
|
|
WHERE n.nspname = 'public'
|
|
AND c.relrowsecurity = true
|
|
AND c.relname IN (
|
|
'ledger_events', 'ledger_merkle_roots', 'findings_projection',
|
|
'finding_history', 'triage_actions', 'ledger_attestations',
|
|
'orchestrator_exports', 'airgap_imports'
|
|
);
|
|
")
|
|
|
|
if [ "$TABLES_WITH_RLS" -ne 0 ]; then
|
|
echo "::error::Rollback failed - $TABLES_WITH_RLS tables still have RLS enabled"
|
|
exit 1
|
|
fi
|
|
echo "✓ Rollback successful - RLS disabled on all tables"
|
|
- name: Validate release manifests (production)
|
|
run: |
|
|
set -euo pipefail
|
|
python ops/devops/release/check_release_manifest.py
|
|
|
|
- name: Re-apply RLS migration (idempotency check)
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Re-applying RLS migration to verify idempotency..."
|
|
psql -h $PGHOST -p $PGPORT -U $PGUSER -d $PGDATABASE \
|
|
-f src/Findings/StellaOps.Findings.Ledger/migrations/007_enable_rls.sql
|
|
echo "✓ Migration is idempotent"
|
|
|
|
generate-manifest:
|
|
runs-on: ubuntu-22.04
|
|
needs: [build-test, migration-validation]
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Generate migration manifest
|
|
run: |
|
|
set -euo pipefail
|
|
MIGRATION_FILE="src/Findings/StellaOps.Findings.Ledger/migrations/007_enable_rls.sql"
|
|
ROLLBACK_FILE="src/Findings/StellaOps.Findings.Ledger/migrations/007_enable_rls_rollback.sql"
|
|
MANIFEST_DIR="out/findings-ledger/migrations"
|
|
mkdir -p "$MANIFEST_DIR"
|
|
|
|
# Compute SHA256 hashes
|
|
MIGRATION_SHA=$(sha256sum "$MIGRATION_FILE" | awk '{print $1}')
|
|
ROLLBACK_SHA=$(sha256sum "$ROLLBACK_FILE" | awk '{print $1}')
|
|
CREATED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
cat > "$MANIFEST_DIR/007_enable_rls.manifest.json" <<EOF
|
|
{
|
|
"\$schema": "https://stella-ops.org/schemas/migration-manifest.v1.json",
|
|
"schemaVersion": "1.0.0",
|
|
"migrationId": "007_enable_rls",
|
|
"module": "findings-ledger",
|
|
"version": "2025.12.0",
|
|
"createdAt": "$CREATED_AT",
|
|
"description": "Enable Row-Level Security for Findings Ledger tenant isolation",
|
|
"taskId": "LEDGER-TEN-48-001-DEV",
|
|
"contractRef": "CONTRACT-FINDINGS-LEDGER-RLS-011",
|
|
"database": {
|
|
"engine": "postgresql",
|
|
"minVersion": "16.0"
|
|
},
|
|
"files": {
|
|
"apply": {
|
|
"path": "007_enable_rls.sql",
|
|
"sha256": "$MIGRATION_SHA"
|
|
},
|
|
"rollback": {
|
|
"path": "007_enable_rls_rollback.sql",
|
|
"sha256": "$ROLLBACK_SHA"
|
|
}
|
|
},
|
|
"affects": {
|
|
"tables": [
|
|
"ledger_events",
|
|
"ledger_merkle_roots",
|
|
"findings_projection",
|
|
"finding_history",
|
|
"triage_actions",
|
|
"ledger_attestations",
|
|
"orchestrator_exports",
|
|
"airgap_imports"
|
|
],
|
|
"schemas": ["public", "findings_ledger_app"],
|
|
"roles": ["findings_ledger_admin"]
|
|
},
|
|
"prerequisites": [
|
|
"006_orchestrator_airgap"
|
|
],
|
|
"validation": {
|
|
"type": "rls-check",
|
|
"expectedTables": 8,
|
|
"expectedPolicies": 8,
|
|
"tenantFunction": "findings_ledger_app.require_current_tenant"
|
|
},
|
|
"offlineKit": {
|
|
"includedInBundle": true,
|
|
"requiresManualApply": true,
|
|
"applyOrder": 7
|
|
}
|
|
}
|
|
EOF
|
|
|
|
echo "Generated migration manifest at $MANIFEST_DIR/007_enable_rls.manifest.json"
|
|
cat "$MANIFEST_DIR/007_enable_rls.manifest.json"
|
|
|
|
- name: Copy migration files for offline-kit
|
|
run: |
|
|
set -euo pipefail
|
|
OFFLINE_DIR="out/findings-ledger/offline-kit/migrations"
|
|
mkdir -p "$OFFLINE_DIR"
|
|
cp src/Findings/StellaOps.Findings.Ledger/migrations/007_enable_rls.sql "$OFFLINE_DIR/"
|
|
cp src/Findings/StellaOps.Findings.Ledger/migrations/007_enable_rls_rollback.sql "$OFFLINE_DIR/"
|
|
cp out/findings-ledger/migrations/007_enable_rls.manifest.json "$OFFLINE_DIR/"
|
|
echo "Offline-kit migration files prepared"
|
|
ls -la "$OFFLINE_DIR"
|
|
|
|
- name: Upload migration artefacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: findings-ledger-migrations
|
|
path: out/findings-ledger/
|
|
if-no-files-found: error
|