Commit Graph
9 Commits
Author SHA1 Message Date
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