Reedtrullz/Innsats-appen
GitHub: Reedtrullz/Innsats-appen
面向挪威民防现场作业的离线优先 PWA,将整理过的知识库转化为离线可用的任务管理、检查清单、地图与日志工具。
Stars: 0 | Forks: 0
# Beredskapsboka / Innsats-appen
这是一款 Offline-first 的移动端现场支持 PWA 应用,旨在事件发生前、发生时和发生后,为基于可靠信息来源的挪威民防局(Sivilforsvaret)决策提供支持。
- Repository:https://github.com/Reedtrullz/Innsats-appen
- 生产域名:https://innsats.reidar.tech
- GHCR image namespace:`ghcr.io/reedtrullz/innsats-appen`
- 当前线上 SHA 事实来源:`curl -fsS https://innsats.reidar.tech/api/health`,以及与该确切 SHA 对应且已完成的 GitHub Actions 运行记录。请勿将 markdown 文件视为永久的线上版本;仅包含文档的提交也会部署不可变的 image。参见 `docs/release/current-deployment-status.md`。
## 这是什么
Beredskapsboka/Innsats-appen 将精心整理的 Obsidian 知识库转化为一个本地/离线的操作支持应用,适用于 Sivilforsvaret 风格的现场工作。它专为在网络连接不稳定情况下的快速移动端使用而设计,提供基于来源的快速卡片、本地任务上下文、检查清单、地图/日志记录、行动后导出以及隐私安全的本地重置功能。
该应用仅用于决策支持。它不是官方的指挥、命令、日志、追踪、警报或存档系统。除非用户手动导出或复制,否则本地浏览器数据将保留在设备上。
## 当前应用功能
- 基于来源的快速卡片、搜索、阶段页面和专家模块,用于在事件发生前/发生时/发生后(før/under/etter innsats)提供支持。
- 本地任务看板,包含活动阶段、角色/场景上下文、下一步建议行动、检查清单进度、命令/通信导出工具、公共上下文信号以及发布安全的本地重置功能。
- Kart → Logg → Oppdrag → Etterrapport → Oppdragsmappe 工作流:
- 可选的应用本地 MapLibre/PMTiles 包,并提供示意图降级方案,
- 基于任务的标记、扇区/teiger 以及 GeoJSON/SVG 导出,
- 明确的 `Logg herfra` 操作和活动任务现场日志摘要,
- 经过脱敏处理的行动后报告和任务文件夹导出元数据。
- Feltmodus/glove-mode 快捷操作,用于地图、日志、活动任务、检查清单、5-punktsordre、sambandsplan、状态导出和搜索。
- Offline-first 的 PWA 架构,具备 service-worker/缓存验证、严格的客户端 CSP,且运行时不会向外部 tile-provider 发起请求。
- 为 `/release` 面板生成的工作计划/发布元数据,数据源自本地 `.hermes/plans` 并镜像到安全的生成 JSON 中。
## GitHub repository 元数据
推荐的 GitHub About 描述:
```
Offline-first Norwegian Civil Defence field-support PWA with local missions, checklists, map/log workflow and privacy-safe exports.
```
推荐的主题/标签:
```
pwa, offline-first, emergency-preparedness, civil-defense, sivilforsvaret, incident-response, field-operations, nextjs, typescript, service-worker, pmtiles, maplibre, privacy-first, norwegian, preparedness, checklists, field-logging
```
## 环境要求
- Node 22.x。在 Reidar 的机器上,请使用:
source ~/.nvm/nvm.sh && nvm use 22
- 通过 Node 22 运行的 npm 10.x。
- 安装 Playwright 浏览器以进行 E2E 检查(如果缺失,请运行 `npx playwright install chromium`)。
- 可选(用于实时 MET 天气上下文):在生产环境使用前,请将 `MET_USER_AGENT` 设置为包含真实联系信息的 user agent。
## 事实来源
Obsidian 知识库是资源摘录和项目笔记的来源。请使用以下命令进行配置:
```
OBSIDIAN_BEREDSKAPSBOKA_PATH=/path/to/your/Obsidian/Beredskapsboka
```
精心整理的 MVP 内容位于 `content/curated/*.yaml`。构建脚本会将其编译到 `content/generated/*`,并将浏览器可读的 JSON 镜像到 `public/generated-content/*`。经过脱敏处理的 `content/generated/source-documents.json` 快照及其受追踪的 `content/generated/source-snapshot-metadata.json` 副文件会被提交,这样干净的 GitHub Actions/Docker runner 即使无法访问私有 Obsidian vault 也能进行构建和测试,同时保留来源快照的新鲜度元数据;请使用 `npm run build:content` 刷新这两者,并在提交更改前依赖隐私测试。
在本地开发时,工作计划位于 `.hermes/plans/*.md` 中。`npm run sync:workplans` 会将安全的元数据/任务标题提取到 `content/workplans/workplans.json` 中,镜像 `content/generated/workplans.json` + `public/generated-content/workplans.json`,并在 vault 可用时将 `20-Workplans.md` 写入 Obsidian 项目文件夹。`/release` 会从 `/generated-content/workplans.json` 获取生成的工作计划静态产物,并将其合并到浏览器本地的发布面板中,同时保留本地的状态覆盖;dette er en statisk artefakt uten backend-synk。
## 应用命令
```
source ~/.nvm/nvm.sh && nvm use 22
npm install
npm run dev # local Next dev server
npm run build:content # import Obsidian, compile curated YAML, build search index, generate workplan artifacts, validate graph/artifacts
npm run sync:workplans # generate safe .hermes/plans metadata into Obsidian + generated local workplan artifacts for /release
npm run typecheck # TypeScript gate
npm run test # Vitest unit/component/integration/security/content tests
npm run build # content build + production Next build
npm run e2e # build + production-mode Playwright E2E (service worker/offline checks)
npm run e2e:prod # same build + production-mode E2E alias; set PLAYWRIGHT_PORT=3007 if local port 3000 is busy
npm run e2e:prod:no-build # production-mode Playwright E2E against an existing production build
npm run check # alias for check:ci
npm run check:ci # build content + typecheck + lint + Vitest + production build + production E2E + perf budgets
```
实用的定向检查关卡:
```
npm run test -- tests/content/coverage.test.ts
npm run test -- tests/security/privacy-boundaries.test.ts
npm run test -- tests/maps/maplibre-runtime.test.ts
npm run e2e:prod -- tests/e2e/core-mobile-journey.spec.ts
npm run e2e:prod -- tests/e2e/offline.spec.ts
npm run e2e:prod -- tests/e2e/map-log-mission-flow.spec.ts tests/e2e/offline-map.spec.ts
```
## 当前应用界面
- `/`、`/sok`、`/hurtigkort`、`/for`、`/under`、`/etter`、`/kilder` 和 `/moduler/*` 提供操作指挥入口点、本地/离线搜索、基于来源的卡片、阶段页面、来源视图和专家模块。
- `/oppdrag/ny` 创建本地任务上下文;`/oppdrag` 显示活动任务看板,包含态势、下一步建议行动、推荐卡片、匹配的检查清单进度、地图/日志摘要、行动后/任务文件夹导出、命令/通信导出工具,以及缓存/过期的公共上下文信号。
- `/kart`、`/under`、Feltmodus 快捷操作和 `/oppdrag` 支持仅在本地运行的 Kart → Logg → Oppdrag → Etterrapport → Oppdragsmappe 工作流,详见 `docs/map-log-fieldmode-workflow.md` 中的文档。MapLibre/PMTiles 包是可选的本地资产;该应用在运行时必须仍能使用示意图降级方案工作,且绝不能请求外部 tile-provider URL。
- `/mer` 汇集了辅助支持界面:来源、学习/模块、地图、Feltmodus、隐私、设备数据控制和管理链接。
- `/release` 是一个独立的发布就绪看板,用于发布规划、阶段关卡、正在进行的工作、生成的本地工作计划产物、风险关注点、本地 JSON 导出和发布材料链接。它特意避开了操作应用架构,并且 ingen backend-synk。
## 运行手册
1. 激活 Node 22。
2. 在任何内容编辑后,使用 `npm run build:content` 构建内容。
3. 提交前运行 `npm run test` 和 `npm run typecheck`。
4. 在进行生产/移动/离线验证之前运行 `npm run build`。
5. 运行 `npm run e2e:prod` 以验证生产环境架构、service worker、离线流程、本地任务存储、隐私重置和移动端用户旅程。
6. 在声称达到试运行就绪状态之前,请运行 `npm run check:ci`,验证确切 SHA 对应的 GitHub Actions 运行状态为 `completed/success`,验证生产环境 `/api/health` 返回相同的 SHA,并在实际进行测试之前,将真机/预发布环境的证据阻碍因素保持为明确状态。
## 部署
用于 `https://innsats.reidar.tech` 的 Ansible/GHCR 部署设置位于 `deploy/` 目录中。
自动化的 CI/CD 在 `.github/workflows/ci.yml` 中配置:
1. 针对 `main` 的 Pull request 和推送会运行自动检查:高危/严重级别的 npm audit、工作计划新鲜度、内容构建、TypeScript、ESLint、Vitest、生产构建、移动端 JS 预算、Lighthouse 移动端预算以及 Playwright 生产环境 E2E。
2. 只有在这些检查在 `main` 上通过后,GitHub Actions 才会构建并推送 `ghcr.io/reedtrullz/innsats-appen:<12-char-sha>` 以及 `:latest`。
3. 然后,部署任务会通过 SSH 运行 `deploy/playbook.yml`,并验证 `https://innsats.reidar.tech/api/health` 返回的是所推送的确切提交 SHA。
部署工作流需要包含 `deploy@198.23.137.16` 用户私钥的 repository secret `VPS_SSH_PRIVATE_KEY`,以及 `deploy/README.md` 中描述的已配置的 VPS host-key pin。
依然支持手动本地部署:
```
./deploy/publish-and-deploy.sh
```
有关先决条件、GHCR 登录说明和 VPS 验证命令,请参见 `deploy/README.md`。
## MVP 边界
有关完整的边界政策,请参见 `docs/mvp-boundaries.md`。简而言之:MVP 中不包含登录、没有后端任务同步、没有实时追踪、没有推送通知、没有患者/个人数据(persondata)、没有集中式事件数据库、没有官方指挥系统集成、没有真实的 Nødnett/samband 标识符,也没有私有/受保护的避难所(skjermede tilfluktsrom)数据。
## 内容编辑
有关如何添加卡片、来源文档、警告/状态以及生成内容的验证,请参见 `docs/content-editing.md`。
标签:MapLibre, PWA, 云安全态势管理, 任务决策支持, 前端应用, 应急管理, 民防, 特征检测, 离线优先, 系统提示词, 自动化攻击, 请求拦截