fix(tracker-web): versioned BFF base /api/v1 + build .dockerignore (GT-447) #48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Evolith Contract Conformance | |
| # CD-01 — detect drift between the Evolith Core contract set this satellite pins | |
| # (contracts/evolith-core-contracts.json) and the set Core actually publishes. | |
| # | |
| # Source of truth is the PUBLIC npm package @beyondnet/evolith-contracts, whose | |
| # MACHINE_CONTRACT_SET export carries the SemVer-bounded public schema set with its sha256 | |
| # digests. It is chosen over the two alternatives because it is the only one reproducible in | |
| # CI without extra trust: | |
| # * a checkout of beyondnetcode/evolith_arch32 needs a cross-repo PAT that the default | |
| # GITHUB_TOKEN cannot provide, so it cannot be the gating source — it is used as an | |
| # OPTIONAL byte-level cross-check when CORE_REPO_TOKEN happens to be configured; | |
| # * GET /api/v1/capabilities is a live, environment-dependent endpoint that is not | |
| # reachable from a hosted runner and whose answer depends on which Core is deployed — | |
| # unusable as a build gate (that check belongs at Tracker boot; see CD-02 / ADR T-039). | |
| on: | |
| push: | |
| branches: [main, develop] | |
| paths: | |
| - "contracts/**" | |
| - ".github/workflows/evolith-contract-conformance.yml" | |
| pull_request: | |
| branches: [main, develop] | |
| schedule: | |
| # Upstream can drift without any commit here, so poll weekly. | |
| - cron: "17 6 * * 1" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| conform: | |
| runs-on: ubuntu-latest | |
| env: | |
| # Mapped to env so the step-level `if` can test it; the `secrets` context is not | |
| # dependable inside step conditionals. | |
| CORE_REPO_TOKEN: ${{ secrets.CORE_REPO_TOKEN }} | |
| steps: | |
| - name: Checkout Tracker | |
| uses: actions/checkout@v4 | |
| with: | |
| path: tracker | |
| - name: Checkout Evolith Core (optional byte-level cross-check) | |
| id: core | |
| if: env.CORE_REPO_TOKEN != '' | |
| continue-on-error: true | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: beyondnetcode/evolith_arch32 | |
| token: ${{ secrets.CORE_REPO_TOKEN }} | |
| path: core | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22" | |
| - name: Resolve pinned upstream contract package | |
| run: | | |
| set -euo pipefail | |
| version="$(node -p "require('./tracker/contracts/evolith-core-contracts.json').source.version")" | |
| name="$(node -p "require('./tracker/contracts/evolith-core-contracts.json').source.package")" | |
| echo "Installing ${name}@${version} from the public npm registry" | |
| mkdir -p upstream | |
| npm install --no-save --no-audit --no-fund --prefix upstream "${name}@${version}" | |
| # CD-01 (agujero encontrado en la pasada de verificacion adversarial): el paso anterior | |
| # instala la version EXACTA del manifiesto, de modo que el guardian nunca podia enterarse de | |
| # que el Core habia publicado una version nueva. El comentario del cron —"upstream can drift | |
| # without any commit here, so poll weekly"— describia una capacidad que no existia: el poll | |
| # semanal reinstalaba siempre lo mismo y salia verde por construccion. Es decir, el escenario | |
| # que ORIGINO este gap —deriva upstream sin commit aqui— seguia vivo en otra forma. | |
| # | |
| # La deriva no rompe los PR ajenos a proposito: que el Core publique no es culpa de quien | |
| # abre un PR, y convertirlo en fallo haria que la gente aprendiera a ignorar este guardian. | |
| # En la ejecucion PROGRAMADA si falla, porque detectar exactamente esto es para lo unico que | |
| # ese cron existe. | |
| - name: Detect upstream contract drift (new published version) | |
| id: drift | |
| run: | | |
| set -euo pipefail | |
| pinned="$(node -p "require('./tracker/contracts/evolith-core-contracts.json').source.version")" | |
| name="$(node -p "require('./tracker/contracts/evolith-core-contracts.json').source.package")" | |
| latest="$(npm view "${name}" version)" | |
| echo "pinned=${pinned}" >> "$GITHUB_OUTPUT" | |
| echo "latest=${latest}" >> "$GITHUB_OUTPUT" | |
| if [ "${pinned}" = "${latest}" ]; then | |
| echo "Pin is current: ${name}@${pinned} is the latest published version." | |
| exit 0 | |
| fi | |
| message="Upstream contract drift: ${name} pins ${pinned} but ${latest} is published. Re-pin the manifest and re-verify the sha256 of every schema; a new minor may promote schemas into the public set (ADR T-038) or change an existing one." | |
| if [ "${{ github.event_name }}" = "schedule" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "::error::${message}" | |
| exit 1 | |
| fi | |
| echo "::warning::${message}" | |
| - name: Verify contract pins against Core's published set | |
| run: | | |
| set -euo pipefail | |
| if [ -d core ]; then | |
| echo "Core checkout present — enabling byte-level schema re-hash." | |
| node tracker/contracts/verify-contract-pins.mjs \ | |
| --manifest tracker/contracts/evolith-core-contracts.json \ | |
| --contract-set upstream \ | |
| --core-repo core | |
| else | |
| echo "Core checkout unavailable — gating on the published npm contract set only." | |
| node tracker/contracts/verify-contract-pins.mjs \ | |
| --manifest tracker/contracts/evolith-core-contracts.json \ | |
| --contract-set upstream | |
| fi | |
| - name: Negative self-test — a corrupted pin MUST fail the guard | |
| run: | | |
| set -euo pipefail | |
| mkdir -p selftest | |
| node -e ' | |
| const fs = require("node:fs"); | |
| const m = JSON.parse(fs.readFileSync("tracker/contracts/evolith-core-contracts.json", "utf8")); | |
| m.schemas[0].sha256 = "0".repeat(64); | |
| fs.writeFileSync("selftest/corrupted.json", JSON.stringify(m, null, 2)); | |
| ' | |
| if node tracker/contracts/verify-contract-pins.mjs \ | |
| --manifest selftest/corrupted.json \ | |
| --contract-set upstream; then | |
| echo "::error::Guard self-test FAILED: a deliberately corrupted pin did not fail the guard." | |
| exit 1 | |
| fi | |
| echo "Guard self-test OK: the corrupted pin was rejected." |