18 Commits
Author SHA1 Message Date
thanhnv 06c404084d feat(casan): add native plugin facade
CASAN Supply Chain and Provenance / verify-scan-attest (push) Canceled after 0s
CASAN CI Gate / Frontend Tests (H3 gate) (push) Canceled after 0s
CASAN CI Gate / CASAN Security Gate + Vault KMS (H4/H5) (push) Canceled after 0s
CASAN CI Gate / Build & Deploy OKR → /opt/webapps/okr (push) Canceled after 0s
CASAN Harness CI / harness (push) Canceled after 0s
2026-08-18 16:26:27 +07:00
thanhnv 9c9efb1043 feat: ship production local assurance viewer in core 2026-07-28 23:09:22 +07:00
thanhnv 777ce342fd ci: avoid setup-node cache cleanup deadlock 2026-07-18 09:19:34 +07:00
thanhnv 4af81ccf40 ci: bound self-hosted runner gate duration 2026-07-18 09:12:44 +07:00
thanhnv d9ca8df2d6 fix: use named frontend workspace in CI 2026-07-18 09:08:19 +07:00
thanhnv 92c20e304c ci: publish verified evidence packs from Gitea runs 2026-07-18 00:18:36 +07:00
thanhnv 881ee01691 feat: prepare CASAN paid PoC release package 2026-07-18 00:07:04 +07:00
thanhnv 040af64191 feat: enforce live supply chain provenance gates 2026-07-10 16:47:45 +09:00
thanhnvandClaude Opus 4.8 98d699d844 ci(release): auto-publish split bundles to Gitea package registry on version tags
.gitea/workflows/release.yml — on push tag v*: assert tag==VERSION, run the governance
gate (must be green), build core/devkit/platform-preview/all-in-one-demo (enterprise
skipped/refused), then PUT each .tar.gz (+.sha256) to the Gitea generic package registry
using ${{ secrets.GITEA_TOKEN }}. Portable via GITHUB_SERVER_URL/OWNER. Guide updated with
the one-time secret setup + release flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:06:28 +09:00
thanhnvandClaude Opus 4.8 36a4812ef3 refactor(structure): promote app to repo root + remove redundant workspace cruft
Standard production layout: the OKR app (was nested under AINative_OKR_CASAN5/) is now
the repository root. No more wrapper directory.

- Promote AINative_OKR_CASAN5/* -> repo root (backend/ frontend/ packages/ apps/
  .specify/ docs/ infra/ nginx/ scripts/ + configs). Merge tool dirs: .gitea (kept the
  active deploy ci.yml, added harness-ci.yml + runbooks), .claude (agents/commands +
  launch.json), .github moved up.
- Remove redundant: 00_SUBMISSION_PACKAGE, scattered root notes (FPT_CASAN_Full.md,
  tu-tuong-casan.md, casan-tu-sinh..., casan_harness_assessment.md, source-review...,
  README_CASAN5_REFINED.md), casan-next-plans/ and optimize-docs/ (competition/planning
  artifacts — roadmap + design history preserved in git log / commit messages).
- Update all references to the old layout:
  - .gitea/workflows/{ci,harness-ci}.yml, .github/workflows/{ci,deploy}.yml:
    working-directory .; drop AINative_OKR_CASAN5/ prefix; .specify/{tests,scripts}
    -> packages/casan-harness/... (.specify/logs state kept)
  - .claude/launch.json, .gitea/*-runbook.md: path prefixes
  - CLAUDE.md, README.md: docs/input -> apps/okr/domain/input
  - policy-bundle.yaml: 8 policy paths -> packages/casan-harness/...; manifest re-signed
- secrets-scan.sh: fixture excludes -> new package/domain paths.

Full gate from the new root: PASS=64 FAIL=0 SKIP=3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 13:26:36 +09:00
thanhnvandClaude Opus 4.8 c0f61166a0 fix(ci): self-heal mysql env-file read access in deploy preflight
docker compose reads env_file client-side as the deploy user (ubuntu), so
the root-managed /opt/webapps/webapp-mysql.env (mode 600) caused
"open ...: permission denied" at `docker compose up`. Extend the deploy
preflight to grant docker-group read (chgrp docker + chmod 640) when the
deploy user cannot read it — idempotent, self-heals a rebuilt web VPS.
The live VPS file was already fixed out-of-band; this prevents recurrence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 22:09:53 +09:00
thanhnvandClaude Opus 4.8 82011a0c67 fix(ci): eliminate audit-signature flake + self-heal deploy docker access
Two comprehensive CI fixes:

1. Adversarial harness flake (PASS=42 FAIL=2, state-dependent):
   governance-check.sh re-exported audit-public.pem only when GENERATING a
   new signing key. On a CI runner where the off-repo private key PERSISTS
   across runs, the checked-out (Vault-signed) audit-public.pem drifted out
   of sync with the local re-signing key, so verify-audit-chain.sh rejected a
   genuine head ("H5/H2 verifies the genuine signed chain"). Now always
   re-export the public key matching the signing key — mirrors the same fix
   already applied to tool-audit-lib.sh (c31987c). Reproduced the exact
   FAIL=2 locally with a drifted persisted key; now deterministically 44/44.

2. Deploy docker.sock permission denied:
   Added a self-healing preflight to deploy-okr that ensures the deploy user
   is in the docker group on the web VPS (idempotent, passwordless sudo) and
   proves a fresh SSH session can reach the daemon before streaming images.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 21:44:20 +09:00
thanhnvandClaude Sonnet 4.6 cf467ed829 fix(ci): write DEPLOY_SSH_KEY via env var + strip CR + ensure trailing newline
printf '%s' with inline secret expansion could leave out trailing newline
or preserve \r from browser-pasted keys, causing OpenSSH 'error in libcrypto'.
Use env: block + printf '%s\n' | tr -d '\r' to normalize the key file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 19:04:34 +09:00
thanhnvandClaude Sonnet 4.6 f6cc723bf4 fix(ci): security-gate auto-installs frontend deps if vitest missing
Instead of skipping the frontend test when vitest is not installed,
security-gate.sh now runs `npm ci -w frontend` automatically.

Also add `cache: "npm"` to security-gate's actions/setup-node so the
npm cache from the frontend-tests job is reused — prevents OOM on
the 1GB VPS (cache restore is disk-only, not 300MB download).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 17:27:09 +09:00
thanhnvandClaude Sonnet 4.6 9229fee656 feat(deploy): switch to Oracle MySQL, separate CI runner, docker-compose deploy
- Prisma schema: sqlite → mysql provider
- Migration SQL rewritten as MySQL DDL (utf8mb4, DATETIME(3), AUTO_INCREMENT)
- Add migration_lock.toml for mysql provider
- Dockerfile.backend: drop node:22/sqlite deps, use node:20-slim
- entrypoint.sh: replace SQLite first-run logic with prisma migrate deploy + db seed
- docker-compose.prod.yml: production compose for /opt/webapps/okr on web VPS
  - reads DB creds from /opt/webapps/webapp-mysql.env
  - reads app secrets from /opt/webapps/okr/.env.app (written by CI)
  - port 80 (frontend), no conflict with Gitea 3000/Vault 8200
- ci.yml deploy-okr: moves from ubuntu-latest (web VPS) to ci-runner (161.33.149.243)
  - builds images on CI runner VPS (no heavy build on web/Gitea VPS)
  - transfers images via docker save | gzip | ssh | docker load
  - deploys via SSH + docker compose up on web VPS
- scripts/setup-ci-runner.sh: one-time setup script for CI runner VPS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 16:37:56 +09:00
thanhnvandClaude Sonnet 4.6 75298f6e4c fix(ci): remove npm ci from security-gate — OOM-killed act-runner on 1GB VPS
security-gate job was downloading ~300MB of React/Vite npm packages unnecessarily.
casan-step.mjs uses only node:child_process, node:fs, node:os (built-ins) — no
npm packages needed. Removing npm ci -w frontend saves ~300MB peak RAM in CI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 14:42:46 +09:00
thanhnvandClaude Sonnet 4.6 e83f306971 fix(ci): run security-gate after frontend-tests to prevent OOM on 1GB VPS
Both jobs running concurrently (two 512MB containers + gitea + vault) exhausted
the 1GB RAM. Make security-gate sequential with needs: [frontend-tests].
Also fix health-check to use docker ps instead of curl localhost (DooD mode).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 13:47:20 +09:00
thanhnvandClaude Sonnet 4.6 72d3e56308 ci: add root-level workflow for Gitea Actions
Gitea Actions requires the workflow file at repo root (.gitea/workflows/ci.yml)
not in the app subdirectory. Uses defaults.run.working-directory: AINative_OKR_CASAN5
so all run steps execute in the correct app context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 13:02:03 +09:00