Skip to content

fix(tracker-web): versioned BFF base /api/v1 + build .dockerignore (GT-447) #48

fix(tracker-web): versioned BFF base /api/v1 + build .dockerignore (GT-447)

fix(tracker-web): versioned BFF base /api/v1 + build .dockerignore (GT-447) #48

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."