atk0309/project_ZeroDay
GitHub: atk0309/project_ZeroDay
一套基于 TypeScript/Fastify 构建的 ARG 风格顺序解谜竞赛平台,专为小规模黑客主题教育活动设计,集成了闯关引擎、反作弊系统和管理后台。
Stars: 1 | Forks: 0
```
███████╗███████╗██████╗ ██████╗ ██████╗ █████╗ ██╗ ██╗
╚══███╔╝██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔══██╗╚██╗ ██╔╝
███╔╝ █████╗ ██████╔╝██║ ██║██║ ██║███████║ ╚████╔╝
███╔╝ ██╔══╝ ██╔══██╗██║ ██║██║ ██║██╔══██║ ╚██╔╝
███████╗███████╗██║ ██║╚██████╔╝██████╔╝██║ ██║ ██║
╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
s e q u e n t i a l h a c k e r h u n t
```







# ZeroDay ARG — 顺序黑客狩猎
一个面向约 10–30 名 11/12 年级学生的多子域名 ARG 风格黑客寻宝游戏。剧情融合了**《黑客帝国》**、**《黑客》(1995)** 和**《战争游戏》**,并带有真实的黑客传奇色彩(Mitnick、Poulsen、Torvalds 等)。玩家将被招募进一个神秘的组织,必须通过 19 项试炼才能“攻破 GIBSON”。
## 游戏玩法
**顺序试炼。** 每位玩家每次推进一个阶段 —— 只有在解决第 N 项后,第 N+1 项才会开启。卡住太久?管理员可以手动帮他们跳过某个阶段;排行榜会用 `⚠` 标记这种辅助。
**D-Day 倒计时。** 整个体验由一个巨大的终端绿倒计时时钟驱动。发布前,它会倒数至 **GIBSON GOES LIVE**;在 T-0 时,它会翻转倒数至 **GIBSON GOES COLD**。当第二个计时器归零时,排行榜将冻结,最终挑战将永远锁定。
**随时招募,D-Day 前进入受限大厅。** 注册 + magic-link 会立即生效。在正式发布前,被招募的操作员会看到一个 CRT 主题大厅,其中包含倒计时、邀请名额、同期学员墙以及带有氛围感的 `tail -f` 效果 —— 没有任何挑战列表。在 T-0 时,该页面会过渡到中心枢纽。
**操作员发放邀请。** 每位操作员会获得两个邀请名额(可配置)。待处理和已接受的邀请会占用名额;撤销或过期则会释放名额。Token 将在 72 小时后失效。需要第三个名额?请询问管理员 —— 控制台中有一个包含批准/拒绝操作的请求流程。
**玩家专属 flag。** 每个 flag 都会根据用户专属的 salt 进行 HMAC 处理。在操作员之间共享 flag **不会**共享访问权限 —— Bob 的提交 endpoint 会拒绝 Alice 的 flag。两次提供 flag 会导致提供者被冻结;一次使用他人的 flag 会导致使用者被冻结。
**控制台驱动所有设置。** 运行时的值不需要配置 `.env`。操作员访问 `/admin`,通过一个故意设计得很古怪的、点击 5 次空字段的彩蛋来设置引导密码,然后通过 UI 配置启动/结束时间戳和邮件子系统(Resend 或 SMTP)。
## 快速开始
```
# 前提条件:Node 24 LTS 以及 Python 3、make,和用于
# 原生 Argon2 和 SQLite 模块的 C++ 编译器。Docker 可以避免使用本地 toolchain。
git clone https://github.com/atk0309/project_zeroday
cd project_zeroday
npm ci
cp .env.example .env
# 编辑 .env — 运行时只需要关心 SESSION_SECRET、FLAG_SECRET 和 PUBLIC_ORIGIN。
npm run migrate # create SQLite schema + seed challenge registry
npm run dev # tsx watch on port 3000
# 在另一个 terminal 中:
open http://localhost:3000/admin # initialize the game (see docs/operator.md)
```
通过 Caddy + Docker Compose 的生产环境部署位于 `ops/` 目录中 —— 请参阅 [`docs/operator.md`](docs/operator.md)。Railway 托管文档请见 [`docs/hosting-railway.md`](docs/hosting-railway.md)。
## 项目结构
```
app/src/
challenges/
registry.ts # the 19 challenges, ordered 1 → 19, with metadata
types.ts # ChallengeModule interface
handlers/
index.ts # id → handler module mapping; stub fallback
stub.ts # placeholder for unauthored challenges
*.ts # one file per authored puzzle
cron/dripHints.ts # 09:00 stuck-detection job
db/
index.ts # SQLite singleton + path resolution
schema.sql # tables (users, challenges, solves, app_settings, …)
migrate.ts # apply schema + additive ALTERs + seed registry
lib/
adminAuth.ts # admin sessions, password, magic-link
audit.ts # admin_audit_log writer
cheat.ts # strike system, dossiers, admin recovery
cheatDetect.ts # shape-gated flag-supplier reverse lookup
content.ts # email + lobby copy (seeded defaults, token interp)
flags.ts # generateFlag(user, challengeId) — HMAC, per-player salt
gibson.ts # GIBSON key fragments + status for the setup panel
hints.ts # cost curve + labels
invitations.ts # operator invite quota, claim flow, sweep
inviteRequests.ts # operator → admin extra-slot requests
mail.ts # Resend + SMTP wrapper, env-seed
phase.ts # uninitialized | prelaunch | live | frozen
playerAuth.ts # signup, magic-link, sessions
progress.ts # ordinal advance + admin skip (transactional)
settings.ts # app_settings cache (30s TTL, write-through)
middleware/
adminAuthMiddleware.ts
playerAuthMiddleware.ts # loadPlayer / requirePlayer / enforcePlayerState
routes/
admin/login.ts # the 5-click easter egg + 3-mode login
admin/setup.ts # first-run wizard (timing, review) + /admin/account (password, sessions, mail)
admin/dashboard.ts # KPIs, players, hints, audit, JSON drawer API
admin/templates.ts # email + lobby copy workspace
admin/invitations.ts # admin JSON API + public /claim/:token
hub.ts # main player terminal at hack.example.com
lobby.ts # operator-side invite endpoints
leaderboard.ts # /board + /api/leaderboard
recruit.ts # red/blue pill landing
submit.ts # POST /api/submit, advances current_ordinal
strikeNotice.ts # /strike-notice (supplier) + /frozen (consumer)
privacy.ts # GET /privacy — cookie + analytics disclosure
server.ts # Fastify bootstrap, host-based subdomain dispatch, consent-banner onSend hook
app/test/ # vitest — see "Testing" below
assets/ # author-side puzzle assets, NOT served via /static (e.g. c17/cover.png)
ops/ # Caddyfile, docker-compose.yml, Dockerfile
scripts/check-base.mjs # pretest guard: refuse stale-branch test runs
tools/ # author helpers (stego-encode.py for #17, …)
web/views/
admin/ # login, setup, account, dashboard (dense + narrative),
# players, feed, hints, _topbar / _sidenav / _drawer / _head
# _players_invitations / _requests / _emails tabs
hub.ejs / lobby.ejs / leaderboard.ejs / locked.ejs
uninitialized.ejs / manual.ejs # hub.ejs covers live + frozen + completed
recruit-step1.ejs / recruit-decide.ejs / recruit-step2.ejs / recruit-blue.ejs
claim.ejs / claim-dead.ejs # invitation claim flow
account-frozen.ejs / strike-notice.ejs # anti-cheat takeover screens
privacy.ejs # /privacy — cookie + analytics disclosure
web/static/
terminal.css + terminal.js # lobby/hub/leaderboard UI (countdown, polling)
recruit-flow.css + recruit-flow.js # CRT recruit theme + typewriter / boot
violation.css # cheater + supplier vocabulary (klaxons, dossier)
admin.css # operator-grade CRT vocabulary
admin.js # drawer fetch, hint dropdowns, 5s feed polling
consent.css + consent.js # cookie-consent banner + Clarity gate (injected on public pages)
.github/ # CI, Dependabot, issue forms, pull-request template
docs/ # operator + challenge-authoring + hosting guides
```
## 技术栈
- **运行时**:Node 24 LTS、TypeScript (ES modules)
- **Web**:Fastify 5 + `@fastify/{cookie, formbody, view, static, rate-limit}`
- **DB**:通过 `better-sqlite3` 实现的 SQLite(同步模式,对于约 30 名并发玩家来说性能完全足够)
- **模板**:通过 `@fastify/view` 实现的 EJS
- **Auth**:使用 argon2id 作为管理员密码;使用 HMAC-SHA256 作为玩家专属 flag
- **邮件**:Resend (HTTP API) 或 SMTP (nodemailer) —— 在运行时通过管理员控制台进行选择
- **Cron**:`node-cron` (09:00 卡顿检测)
- **测试**:结合 `app.inject()` 进行端到端 HTTP 测试的 vitest 4
- **运维**:Caddy(通过 Cloudflare DNS-01 实现泛域名 TLS)+ Docker Compose,或者 Railway
## 测试
```
npm run check # type check + vitest; pretest runs check-base.mjs
npm run build # emit production JavaScript
npm run audit # fail on high/critical dependency advisories
npm run test:watch # interactive
CHECK_BASE_SKIP=1 npm test # bypass the "is your branch behind dev?" guard
```
如果当前的 `claude/*` 分支落后于 `origin/dev`,`scripts/check-base.mjs` 将判定测试运行失败。CI 会设置 `CI=true`,因此该检查在那里会被跳过。在新会话中的经验法则:首先在 `origin/dev` 上进行 rebase,然后再进行编辑。
CI 会在 Node 24 LTS 上重复执行锁定的安装、审计、类型检查和测试套件,
然后构建生产容器并进行 HTTP 冒烟测试。第三方 Actions
和生产镜像均被固定为不可变的摘要;Dependabot 会针对 `dev` 提出兼容的更新建议。
## 状态
| 组件 | 状态 |
|---|---|
| 顺序引擎 | ✅ |
| D-Day 阶段状态机 + 倒计时 | ✅ |
| 玩家专属加盐 flag 引擎 | ✅ |
| 管理员引导(5 次点击彩蛋) | ✅ |
| 管理员登录(3 种模式:未初始化 / 密码已设置 / 邮件已配置) | ✅ |
| 管理员设置向导(时间设置、审查) | ✅ |
| 管理员仪表板 —— 密集的运维数据 + 剧情变体(cookie 切换) | ✅ |
| 玩家详情抽屉(`GET /admin/api/player/:id`) | ✅ |
| 玩家列表上的搜索 + 仅卡顿过滤器 | ✅ |
| KPI 迷你图(活跃 <1 小时、提交/小时) | ✅ |
| 实时 feed 轮询(`GET /admin/api/events?since=`,5 秒间隔) | ✅ |
| 每行提示下拉菜单(L1–L5,可编辑正文,带有审计标签) | ✅ |
| 反作弊检测 + 2 次警告系统 + 管理员恢复 | ✅ |
| 作弊者接管 + 供应商“我们注意到了”体验 | ✅ |
| 管理员账户页面 —— 密码轮换 + 会话 + 邮件 | ✅ |
| 每个会话的撤销(`POST /admin/account/sessions/:id/revoke`) | ✅ |
| 玩家 magic-link auth + 会话 | ✅ |
| 大厅 / 中心枢纽 / 锁定 / 冻结 / 未初始化视图 | ✅ |
| 排行榜(阶段 X/19 + 积分 + ⚠) | ✅ |
| 滴漏提示 cron(仅排队;仍需管理员点击) | ✅ |
| 招募落地页(红/蓝药丸,记忆消除告别) | ✅ |
| 位于 `/manual` 的操作员手册 | ✅ |
| 邀请后端 —— 操作员名额、认领流程、管理员覆盖、请求 | ✅ |
| 邮件模板工作区(6 个系列 + 大厅风味,实时预览,测试发送) | ✅ |
| Caddyfile + docker-compose | ✅ |
| Railway 托管文档(生产环境 + 模拟环境) | ✅ |
| **已创作的挑战** | 事实来源:`handlers/index.ts` 中的 `authoredChallengeIds()`。全部 19 个已创作。存根处理程序保留为引擎后备。 |
| GIBSON 关键部分 | `lib/gibson.ts` 中的 `gibsonKeyStatus()`。全部 3 个已连接(#7、#13、#17)并被 #19(`hack-the-planet`)使用。 |
| OSINT 页面 (#18) | ✅(`ghost-shell` —— `mitnick.example.com/staff` 上的每个玩家专属剧情秘密,通过 `/robots.txt` 提供面包屑导航) |
| Git repo seed (#16) | ✅(`tools/git-seed.sh` 将规范秘密植入公共仓库的历史记录中) |
| 学员矩阵视图(操作员 × 试炼热力图) | 延期 |
| `tools/stego-encode.py` | ✅(覆盖图生成 + 参考编解码器) |
如需查看实时测试计数,请运行 `npm test` —— vitest 会进行报告。
## 更多文档
- [`CLAUDE.md`](CLAUDE.md) —— 不变量、陷阱、代码路径。**对于接手此仓库的 AI 助手来说是必读内容**。
- [`docs/operator.md`](docs/operator.md) —— 首次运行设置、邮件、跳过卡顿玩家、邀请、冻结、恢复
- [`docs/authoring-challenges.md`](docs/authoring-challenges.md) —— 如何编写新的挑战模块
- [`docs/hosting-railway.md`](docs/hosting-railway.md) —— Railway 上的生产环境 + 模拟环境,Cloudflare 泛域名 TLS
## 许可证
该项目基于 MIT 许可证授权 —— 请参阅 [`LICENSE`](LICENSE)。
版权所有 (c) 2026 atk0309标签:ARG游戏, Fastify, MITM代理, SQLite, TypeScript, 安全插件, 版权保护, 自动化攻击, 黑客游戏