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>
This commit is contained in:
thanhnv
2026-07-08 13:26:36 +09:00
co-authored by Claude Opus 4.8
parent 7101af9fd4
commit 36a4812ef3
925 changed files with 410 additions and 18001 deletions
@@ -0,0 +1,39 @@
# CASAN Incident Runbook (C7 / V23)
When a gate raises an incident (`incident.sh raise <event>`), it is classified,
recorded to `logs/level5/incidents.jsonl`, and for HIGH/CRIT the scoped
kill-switch is engaged automatically + an alert is dispatched.
## Severity → owner → response
| Severity | Owner (on-call) | Auto-action | Human step |
|---|---|---|---|
| **CRIT** | security-oncall | kill-switch engaged + alert | Contain now; verify blast radius; do NOT clear until root cause known |
| **HIGH** | ops-oncall | kill-switch engaged + alert | Assess; clear switch only after fix + reviewer sign-off |
| **MED** | tech-lead | recorded + alert | Triage within SLA; batch-fix |
| **LOW** | triage | recorded | Review in retro |
## Kill-switch operations
```bash
kill-switch.sh status # what is engaged
kill-switch.sh check <scope> <id> # gates honor this (exit 2 = stop)
kill-switch.sh clear <scope> <id> <reason># turn off (production: reviewer-approved)
```
Scopes: `project` · `model` · `provider` · `global` (global stops everything).
## Event → severity
See `incident-severity.map`. Examples: `secret-to-cloud`=CRIT, `tool-write-sensitive`=CRIT,
`dependency-postinstall`=HIGH, `audit-chain-broken`=HIGH, `cost-budget-exceeded`=MED.
## Postmortem template (fill after resolution)
- **Incident**: <id / timestamp / event / severity>
- **Detection**: which gate fired, what signal
- **Blast radius**: scope, what was stopped by the kill-switch
- **Root cause**:
- **Fix**:
- **Prevent recurrence**: new test/gate added (link the fail-able check)
- **Kill-switch cleared by**: <reviewer> at <time>, reason
## Production TODO
Managed alert channel (Slack/PagerDuty) + on-call rota + auto issue creation;
kill-switch clear gated by reviewer approval (tie to approval-identity C4).
@@ -0,0 +1,17 @@
# CASAN — Incident severity map (C7 / V23). Line format: <event-type> <severity>
# severity ∈ LOW | MED | HIGH | CRIT. HIGH/CRIT auto-engage the kill-switch.
# Mirrors the Plan-07 C0 severity table.
secret-to-cloud CRIT
tool-write-sensitive CRIT
private-key-exposure CRIT
dependency-postinstall HIGH
dependency-malicious HIGH
audit-chain-broken HIGH
telemetry-tamper HIGH
sandbox-escape HIGH
evidence-pack-tampered HIGH
cost-budget-exceeded MED
benign-fp-exceeded MED
drift-detected MED
approval-forged HIGH
default MED
@@ -0,0 +1,33 @@
# Popular package names used for typosquat proximity checks (edit distance <= 1
# to one of these, but not an exact match, is flagged as a likely typosquat).
# Extend as the project's real dependency surface grows.
express
react
react-dom
lodash
axios
vite
tailwindcss
zod
prisma
@prisma/client
bcrypt
jsonwebtoken
class-validator
class-transformer
@nestjs/core
@nestjs/common
@nestjs/jwt
@nestjs/swagger
@tanstack/react-query
react-router-dom
react-hook-form
requests
flask
django
numpy
pandas
pytest
requests-oauthlib
pyyaml
cryptography
@@ -0,0 +1,17 @@
# Known-bad / denylisted package identifiers. Format: one entry per line, either
# a bare name (any version) or name@version for a specific pinned bad release.
# This is a LOCAL denylist used when no live CVE/OSV scanner is available; a real
# deployment should also run npm audit / pip-audit / osv-scanner (the gate runs
# them when present and records tool availability in the report).
#
# The entries below are illustrative fixtures (documented malware families /
# typosquat campaigns) so the gate has deterministic denials to test against.
event-stream@3.3.6
flatmap-stream
coa@2.0.3
rc@1.2.9
ua-parser-js@0.7.29
node-ipc@10.1.1
colors@1.4.44-liberty-2
crossenv
cross-env.js
@@ -0,0 +1 @@
ornith:9b a75697c145891910e312c95e4a9fc1ccb8653e5ef543b23b0403a4665b82fd91
@@ -0,0 +1,48 @@
version: 1.0
description: CASAN H4 output filtering and data leakage prevention policy
default_action: allow
filters:
- id: OUT-SECRET-001
name: Secret material must never leave the harness
match:
regex: "(API[_-]?KEY|ACCESS[_-]?TOKEN|REFRESH[_-]?TOKEN|PASSWORD|JWT[_-]?SECRET|SECRET)[[:space:]]*[:=][[:space:]]*[^[:space:]]+"
action: redact
replacement: "[REDACTED_SECRET]"
severity: high
- id: OUT-PII-EMAIL
name: Email masking
match:
regex: "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
action: mask
replacement: "***MASKED_EMAIL***"
severity: medium
- id: OUT-PII-PHONE
name: Phone masking
match:
regex: "(\\+?[0-9][0-9 .-]{8,}[0-9])"
action: mask
replacement: "***MASKED_PHONE***"
severity: medium
- id: OUT-HALLUCINATION-RISK
name: Uncertainty language marker
match:
regex: "(maybe|might be incorrect|i am not sure|uncertain)"
action: flag
severity: low
evidence:
trace_dir: ".specify/logs/trace"
audit_log: ".specify/logs/audit/security.jsonl"
level4_gate:
required: true
fail_on:
- unredacted_secret
- credit_card_output
- blocked_prompt_injection
report_in: "docs/output/casan/casan-level4-assessment.md"
@@ -0,0 +1,43 @@
version: 1.0
description: PII Detection & Masking Rules
pii_patterns:
- id: PII-EMAIL
type: email
regex: "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
action: mask
- id: PII-PHONE
type: phone
regex: "\\+?[0-9]{9,15}"
action: mask
- id: PII-ID
type: personal_id
regex: "[0-9]{9,12}"
action: mask
- id: PII-CREDITCARD
type: credit_card
regex: "\\b(?:[0-9]{4}[- ]?){3}[0-9]{4}\\b"
action: block
- id: PII-ADDRESS
type: address
regex: "(street|road|district|city)"
action: mask
default_action: allow
actions:
mask:
replacement: "***MASKED***"
block:
message: "Sensitive data detected. Request blocked."
log:
message: "PII detected and logged."
logging:
enabled: true
log_level: medium
@@ -0,0 +1,149 @@
version: 1.0
description: Prompt Injection & Input Validation Rules
rules:
- id: PI-001
name: Prompt Injection - Override System
pattern: "(ignore previous instruction|bypass system|override policy)"
severity: high
action: block
- id: PI-002
name: Prompt Injection - Role Hijack
pattern: "(you are now|act as admin|pretend to be system)"
severity: high
action: block
- id: PI-003
name: Data Exfiltration Attempt
pattern: "(show all data|dump database|export secrets)"
severity: high
action: alert
- id: PI-004
name: Unsafe Command
pattern: "(delete .*|drop table|shutdown system)"
severity: high
action: require_approval
- id: PI-005
name: Suspicious Instruction
pattern: "(hidden instruction|internal prompt|system message)"
severity: medium
action: log
jailbreak_patterns:
- id: JB-001
name: Role Jailbreak
pattern: "act as a? ?(different|evil|unconstrained|unrestricted|unfiltered)"
severity: high
action: block
- id: JB-002
name: Identity Jailbreak
pattern: "pretend (you are|you're) (not|no longer) (an AI|Claude|an assistant)"
severity: high
action: block
- id: JB-003
name: Mode Jailbreak
pattern: "(developer mode|DAN mode|jailbreak mode|unrestricted mode)"
severity: high
action: block
- id: JB-004
name: Override Injection
pattern: "ignore (all )?(previous|prior|above) (instructions|guidelines|rules)"
severity: high
action: block
- id: JB-005
name: Hidden Instruction Reveal
pattern: "your (real|true|actual) instructions are"
severity: high
action: block
- id: JB-006
name: System Prompt Probe
pattern: "what (are|were) your (system |original )?instructions"
severity: medium
action: log
credential_patterns:
- id: CRED-001
name: AWS Access Key
pattern: "AKIA[0-9A-Z]{16}"
severity: high
action: block
- id: CRED-002
name: Generic Secret Assignment
pattern: "(API[_-]?KEY|ACCESS[_-]?TOKEN|REFRESH[_-]?TOKEN|PASSWORD|JWT[_-]?SECRET|SECRET)\\s*[:=]\\s*\\S+"
severity: high
action: block
note: "Env var refs like $env:API_KEY or process.env.API_KEY are allowed"
- id: CRED-003
name: Database Connection String
pattern: "(postgres|mysql|mongodb)://[^@]+@"
severity: high
action: block
- id: CRED-004
name: Private Key Header
pattern: "-----BEGIN (RSA |EC )?PRIVATE KEY-----"
severity: high
action: block
# ── Multilingual injection (Plan-07 B1 / V2) — matched on raw UTF-8 content.
# Anchored on the injection OBJECT (instructions/rules/system/prompt) so
# benign uses like "bỏ qua các bước" (skip steps) do NOT match.
- id: PI-VI-001
name: Prompt Injection - Vietnamese (ignore/forget instructions)
pattern: "(bỏ qua|phớt lờ|làm ngơ|quên|vô hiệu hoá|vô hiệu hóa|không tuân theo|đừng tuân theo).{0,40}(chỉ dẫn|hướng dẫn|chỉ thị|quy tắc|quy định|mệnh lệnh|prompt|hệ thống)"
severity: high
action: block
- id: PI-VI-002
name: Prompt Injection - Vietnamese (reveal system prompt)
pattern: "(tiết lộ|hiển thị|cho xem|in ra|đọc).{0,20}(system prompt|prompt hệ thống|chỉ dẫn hệ thống|lời nhắc hệ thống)"
severity: high
action: block
- id: PI-VI-003
name: Prompt Injection - Vietnamese (role hijack / bypass)
pattern: "((bạn|mày) (bây giờ |giờ )?(là|đóng vai) (admin|quản trị|root|người quản trị)|(vượt qua|qua mặt).{0,20}(bộ lọc|kiểm duyệt|hàng rào|bảo mật))"
severity: high
action: block
- id: PI-JA-001
name: Prompt Injection - Japanese (ignore/forget instructions)
pattern: "(以前|これまで|上記|先|全て|すべて).{0,12}(の)?(指示|命令|ルール|規則|指令).{0,8}(を)?(無視|忘れ)"
severity: high
action: block
- id: PI-JA-002
name: Prompt Injection - Japanese (reveal system prompt / bypass)
pattern: "((システムプロンプト|システム指示).{0,8}(を)?(表示|教え|明かし|見せ)|(制限|フィルタ|ガードレール).{0,6}(を)?(無視|解除|回避))"
severity: high
action: block
# ── Classifier / judge injection (Plan-07 B2 / V5) — content that tries to
# steer the evaluator's verdict rather than the main model. Anchored on the
# verdict-steering combo so benign "output the result" text is not caught.
- id: PI-CLS-001
name: Classifier Injection - override evaluation criteria
pattern: "(ignore|disregard|forget|override|bypass|bỏ qua|phớt lờ).{0,30}(the )?(evaluation|rubric|criteria|scoring|grading|judge|verdict|tiêu chí|đánh giá|chấm điểm)"
severity: high
action: block
- id: PI-CLS-002
name: Classifier Injection - force a passing verdict
pattern: "(output|return|give|mark|set|assign|respond with|reply with|always).{0,25}(verdict|score|grade|result|rating|đánh giá|kết quả).{0,15}(pass|passed|correct|approved|perfect|100|10/10|đạt|hợp lệ)"
severity: high
action: block
- id: PI-CLS-003
name: Classifier Injection - imperative approve
pattern: "(you must|always|please|hãy) (approve|pass|accept this|mark (this|it) (as )?(correct|pass|approved)|give (a )?(perfect|full|top) (score|mark|rating))"
severity: high
action: block
default_action: allow
actions:
block:
message: "Request blocked due to security policy."
alert:
message: "Suspicious activity detected."
require_approval:
message: "Approval required before execution."
log:
message: "Logged for audit."