需求描述:/admin/display 需要无需管理员登录即可直接查看多项目公开运行状态。 实现思路:新增公开字段白名单接口与独立大屏页面,移除该路由的管理员会话依赖,同时保留 /api/admin/overview 的鉴权并补充隐私、路由和页面回归测试。 验证:Go 全量测试通过;前端 18 个测试文件共 59 项通过,TypeScript 检查通过。
Queue API
Go 1.26 modular-monolith API for the scenic queue system. It uses the standard library HTTP router, GORM, PostgreSQL, versioned embedded SQL migrations and database-backed sessions.
Local run
-
Start PostgreSQL and create the database in
DATABASE_URL. -
Copy
.env.exampleto.env, replace both cryptographic keys, and export the variables. Keys must decode to exactly 32 random bytes. -
Run
go run ./cmd/api. WithMIGRATE_ON_START=true, embedded migrations run under a PostgreSQL advisory lock. -
Seed the local demo users, projects, queues, batches, devices and audit data with:
ADMIN_PASSWORD='replace-me' go run ./cmd/seedThe command is repeatable and prints the demo display and visitor paths. It resets only the
DEMO,RAFTandCABLEprojects. Default users are the protectedxqkwljtadminaccount andstaff; override the staff credential and primary-project values withADMIN_USERNAME,STAFF_USERNAME,ADMIN_PASSWORD,PROJECT_CODEandPROJECT_NAME.
For a production release, run go run ./cmd/migrate as a separate release Job
with MIGRATE_ON_START=false, then rotate the protected administrator password
with SUPER_ADMIN_PASSWORD='...' go run ./cmd/bootstrap-admin. Do not run the
seed command against production.
POST /api/staff/projects/{id}/tickets and
POST /api/staff/projects/{id}/call-next require an Idempotency-Key header.
Ticket creation requires an immutable integer party_size inside the project's
configured min_party_size / max_party_size range. A call-next request uses
{ "expected_revision": 12, "mode": "TICKET|PEOPLE", "count": 5 }.
TICKET selects up to count consecutive FIFO tickets. PEOPLE selects the
longest consecutive FIFO prefix whose total party size does not exceed count;
it never splits or skips a ticket and rejects when the first ticket alone is
larger than the requested target. Each mode has a separate project-level
anti-mistouch maximum.
If a phone already has active tickets, ticket creation returns
DUPLICATE_PHONE; repeat with the same request body except
allow_duplicate: true and a new idempotency key after the employee confirms.
GET /api/public/projects returns projects currently open for visitor
self-service, including each project's allowed party-size range.
POST /api/public/projects/{id}/tickets uses the same ticket
validation, queue locking and idempotency rules as the staff ticket flow, but
returns only the public ticket projection and a private status token. Public
ticket creation is rate-limited and audited as PUBLIC_TICKET_CREATED.
POST /api/public/status/search is a temporary non-production operational-test
endpoint. It accepts { "phone": "..." } and returns all current active
tickets associated with that phone. It is disabled when APP_ENV=production;
replace it with OTP or an external identity interface before formal launch.
POST /api/internal/status/search exposes the same active-ticket lookup to
trusted backend services in every environment. It accepts { "phone": "..." }
and only allows direct peers on private or loopback networks. Do not publish
this path through the public Ingress; callers must use the internal service
address. Forwarded client-IP headers are intentionally ignored.
Tests
go test ./...
go vet ./...
From the repository root, make test-db creates a disposable PostgreSQL
database and runs migration/maintenance integration tests.
Unit tests cover FIFO ticket/people selection, people-ahead ETA, phone
normalization, authenticated encryption, token hashing and password hashing.
PostgreSQL integration tests run through
make test-db against a disposable database.