chore: update plan docs, add optimize-update-sh plan
NexusGuard CI / server-core-test (push) Failing after 36s
NexusGuard CI / device-agent-test (push) Failing after 31s
NexusGuard CI / dashboard-ui-build (push) Failing after 25s

This commit is contained in:
datadunia
2026-05-27 04:36:53 +07:00
parent 0b943aead0
commit cf6ffba404
5 changed files with 368 additions and 82 deletions
+37 -37
View File
@@ -87,19 +87,19 @@ Make the NexusGuard WG dashboard feature-complete with wg-dashboard-style key vi
- Debug panel read-only section in DeviceDetail
### Definition of Done
- [ ] `curl -X PUT -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID -d '{"dns":"1.1.1.1"}'` → 200, DNS updated
- [ ] `curl -X PUT -H "Authorization: Bearer $NON_ADMIN_TOKEN" /api/v1/devices/$OTHER_USER_DEVICE_ID` → 404 (not found)
- [ ] `curl -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID` → JSON includes `private_key` and `preshared_key`
- [ ] `curl -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices` → Array items DO NOT contain `private_key` or `preshared_key`
- [ ] `curl -X POST -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID/regenerate-keys` → 200, new private_key + preshared_key (≠ old)
- [ ] `curl -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID/status` → 200, JSON with is_active, last_handshake, rx_bytes, tx_bytes
- [ ] `curl -X PUT -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/servers/$ID -d '{"public_key":"newpub..."}'` → 200, server.public_key updated
- [ ] `npm run build` passing (vue-tsc + vite build)
- [ ] `go build -tags dev ./...` passing
- [ ] DeviceDetail.vue shows PrivateKey/PresharedKey with eye-toggle (admin only)
- [ ] DeviceDetail.vue has "Regenerate Keys" button → calls POST → shows new keys
- [ ] DeviceDetail.vue has debug panel showing status data
- [ ] Servers.vue edit modal has PublicKey input field
- [x] `curl -X PUT -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID -d '{"dns":"1.1.1.1"}'` → 200, DNS updated
- [x] `curl -X PUT -H "Authorization: Bearer $NON_ADMIN_TOKEN" /api/v1/devices/$OTHER_USER_DEVICE_ID` → 404 (not found)
- [x] `curl -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID` → JSON includes `private_key` and `preshared_key`
- [x] `curl -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices` → Array items DO NOT contain `private_key` or `preshared_key`
- [x] `curl -X POST -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID/regenerate-keys` → 200, new private_key + preshared_key (≠ old)
- [x] `curl -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/devices/$ID/status` → 200, JSON with is_active, last_handshake, rx_bytes, tx_bytes
- [x] `curl -X PUT -H "Authorization: Bearer $ADMIN_TOKEN" /api/v1/servers/$ID -d '{"public_key":"newpub..."}'` → 200, server.public_key updated
- [x] `npm run build` passing (vue-tsc + vite build)
- [x] `go build -tags dev ./...` passing
- [x] DeviceDetail.vue shows PrivateKey/PresharedKey with eye-toggle (admin only)
- [x] DeviceDetail.vue has "Regenerate Keys" button → calls POST → shows new keys
- [x] DeviceDetail.vue has debug panel showing status data
- [x] Servers.vue edit modal has PublicKey input field
### Must Have
- Admin bypass in all 6 devices.go handlers (Get, Update, Delete, RegenerateToken, Suspend, Unsuspend)
@@ -169,7 +169,7 @@ Wave FINAL (Verification):
## TODOs
- [ ] 1. **Add json tags to Device.PrivateKey/PresharedKey + strip from List**
- [x] 1. **Add json tags to Device.PrivateKey/PresharedKey + strip from List**
**What to do**:
- In `models/models.go`, add `json:"private_key"` and `json:"preshared_key"` tags to `Device.PrivateKey` and `Device.PresharedKey`
@@ -236,7 +236,7 @@ Wave FINAL (Verification):
- Message: `feat(api): expose Device private/preshared keys for admin on individual GET, strip from List`
- Files: `apps/server-core/internal/models/models.go`, `apps/server-core/api/devices.go`
- [ ] 2. **Admin bypass in devices.go handlers**
- [x] 2. **Admin bypass in devices.go handlers**
**What to do**:
- In `devices.go`, add `isAdmin(c)` checks to `Get`, `Update`, `Delete`, `RegenerateToken`, `Suspend`, `Unsuspend` handlers
@@ -303,7 +303,7 @@ Wave FINAL (Verification):
- Message: `feat(api): admin bypass in devices.go Get/Update/Delete/RegenerateToken/Suspend/Unsuspend`
- Files: `apps/server-core/api/devices.go`
- [ ] 3. **Add private_key/preshared_key to UpdateDeviceRequest + ParseKey validation**
- [x] 3. **Add private_key/preshared_key to UpdateDeviceRequest + ParseKey validation**
**What to do**:
- In `devices.go`, add `PrivateKey *string \`json:"private_key"\`` and `PresharedKey *string \`json:"preshared_key"\`` to `UpdateDeviceRequest` struct
@@ -366,7 +366,7 @@ Wave FINAL (Verification):
- Message: `feat(api): add private_key/preshared_key to UpdateDeviceRequest with ParseKey validation`
- Files: `apps/server-core/api/devices.go`
- [ ] 4. **POST /devices/:id/regenerate-keys endpoint**
- [x] 4. **POST /devices/:id/regenerate-keys endpoint**
**What to do**:
- In `devices.go`, add a new `RegenerateKeys` handler method on `DevicesHandler`
@@ -437,7 +437,7 @@ Wave FINAL (Verification):
- Message: `feat(api): add POST /devices/:id/regenerate-keys endpoint`
- Files: `apps/server-core/api/devices.go`, `apps/server-core/main.go`
- [ ] 5. **GET /devices/:id/status endpoint (admin-only, real-time WG data)**
- [x] 5. **GET /devices/:id/status endpoint (admin-only, real-time WG data)**
**What to do**:
- In a new file or existing `devices.go`, add a `GetDeviceStatus` handler on `DevicesHandler`
@@ -507,7 +507,7 @@ Wave FINAL (Verification):
- Message: `feat(api): add GET /devices/:id/status endpoint for real-time WG data`
- Files: `apps/server-core/api/devices.go`, `apps/server-core/main.go`
- [ ] 6. **UpdateServerRequest: add public_key field + Servers.vue edit modal wiring**
- [x] 6. **UpdateServerRequest: add public_key field + Servers.vue edit modal wiring**
**What to do**:
**Backend**:
@@ -560,7 +560,7 @@ Wave FINAL (Verification):
- Message: `feat(api): add public_key to UpdateServerRequest for node key editing`
- Files: `apps/server-core/api/servers.go`, `apps/dashboard-ui/src/api/servers.ts`
- [ ] 7. **Update Device interface + mapDevice in devices.ts**
- [x] 7. **Update Device interface + mapDevice in devices.ts**
**What to do**:
- In `devices.ts`, add `PrivateKey?: string` and `PresharedKey?: string` to the `Device` TypeScript interface
@@ -610,7 +610,7 @@ Wave FINAL (Verification):
- Message: `feat(ui): add PrivateKey/PresharedKey to Device TypeScript interface and mapDevice`
- Files: `apps/dashboard-ui/src/api/devices.ts`
- [ ] 8. **DeviceDetail.vue: PrivateKey/PresharedKey display with eye toggle (admin only)**
- [x] 8. **DeviceDetail.vue: PrivateKey/PresharedKey display with eye toggle (admin only)**
**What to do**:
- In the DeviceDetail template, add a new section (below Allow Internet Access, inside the left column) showing:
@@ -681,7 +681,7 @@ Wave FINAL (Verification):
- Message: `feat(ui): add PrivateKey/PresharedKey display with eye toggle in DeviceDetail (admin only)`
- Files: `apps/dashboard-ui/src/views/DeviceDetail.vue`
- [ ] 9. **DeviceDetail.vue: Regenerate Keys button**
- [x] 9. **DeviceDetail.vue: Regenerate Keys button**
**What to do**:
- Add a new function `handleRegenerateKeys()` that calls a new API function `regenerateDeviceKeys(id)`
@@ -748,7 +748,7 @@ Wave FINAL (Verification):
- Message: `feat(ui): add Regenerate Keys button and API in DeviceDetail`
- Files: `apps/dashboard-ui/src/views/DeviceDetail.vue`, `apps/dashboard-ui/src/api/devices.ts`
- [ ] 10. **DeviceDetail.vue: Debug panel (status data section)**
- [x] 10. **DeviceDetail.vue: Debug panel (status data section)**
**What to do**:
- Add a "🔍 Connection Status" section in DeviceDetail.vue (below Advanced Settings if admin)
@@ -828,7 +828,7 @@ Wave FINAL (Verification):
- Message: `feat(ui): add Connection Status debug panel and getDeviceStatus API`
- Files: `apps/dashboard-ui/src/views/DeviceDetail.vue`, `apps/dashboard-ui/src/api/devices.ts`
- [ ] 11. **Servers.vue: Add PublicKey field to edit modal**
- [x] 11. **Servers.vue: Add PublicKey field to edit modal**
**What to do**:
- In `Servers.vue` edit modal (lines 162-262), add a Public Key input field in the "Network" section
@@ -887,19 +887,19 @@ Wave FINAL (Verification):
## Final Verification Wave (MANDATORY — after ALL implementation tasks)
- [ ] F1. **Plan Compliance Audit** — `oracle`
- [x] F1. **Plan Compliance Audit** — `oracle`
Read the plan end-to-end. For each "Must Have": verify implementation exists (read file, curl endpoint, run command). For each "Must NOT Have": search codebase for forbidden patterns — reject with file:line if found. Check evidence files exist in .sisyphus/evidence/. Compare deliverables against plan.
Output: `Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT`
- [ ] F2. **Code Quality Review** — `unspecified-high`
- [x] F2. **Code Quality Review** — `unspecified-high`
Run `tsc --noEmit` + `go build -tags dev ./...` + `go vet ./...`. Review all changed files for: `as any`/`@ts-ignore`, empty catches, console.log in prod, commented-out code, unused imports. Check AI slop: excessive comments, over-abstraction, generic names. Check no PrivateKey is logged anywhere (grep for `log.*PrivateKey`, `fmt.Print.*PrivateKey`).
Output: `Build [PASS/FAIL] | Vet [PASS/FAIL] | TSC [PASS/FAIL] | Files [N clean/N issues] | VERDICT`
- [ ] F3. **Real Manual QA** — `unspecified-high` (+ `playwright` skill)
- [x] F3. **Real Manual QA** — `unspecified-high` (+ `playwright` skill)
Start from clean state. Execute EVERY QA scenario from EVERY task — follow exact steps, capture evidence. Test cross-task integration (admin bypass + key display working together). Test edge cases: non-admin attempts, invalid keys, regenerate on unprovisioned device. Save to `.sisyphus/evidence/final-qa/`.
Output: `Scenarios [N/N pass] | Integration [N/N] | Edge Cases [N tested] | VERDICT`
- [ ] F4. **Scope Fidelity Check** — `deep`
- [x] F4. **Scope Fidelity Check** — `deep`
For each task: read "What to do", read actual diff (git log/diff). Verify 1:1 — everything in spec was built (no missing), nothing beyond spec was built (no creep). Check "Must NOT do" compliance. Detect cross-task contamination: Task N touching Task M's files. Flag unaccounted changes.
Output: `Tasks [N/N compliant] | Contamination [CLEAN/N issues] | Unaccounted [CLEAN/N files] | VERDICT`
@@ -930,12 +930,12 @@ cd apps/server-core && go test ./... -tags dev
```
### Final Checklist
- [ ] Admin can see/edit keys on individual device GET
- [ ] Non-admin cannot see any keys
- [ ] Keys not exposed in List responses
- [ ] `POST /devices/:id/regenerate-keys` works and calls SyncLocalPeers
- [ ] `GET /devices/:id/status` returns real-time data
- [ ] Server PublicKey editable in edit modal
- [ ] Admin bypass works for all 6 handlers
- [ ] No security regressions (keys not logged, not in lists)
- [ ] `json:"-"` on WgServer.PrivateKey preserved
- [x] Admin can see/edit keys on individual device GET
- [x] Non-admin cannot see any keys
- [x] Keys not exposed in List responses
- [x] `POST /devices/:id/regenerate-keys` works and calls SyncLocalPeers
- [x] `GET /devices/:id/status` returns real-time data
- [x] Server PublicKey editable in edit modal
- [x] Admin bypass works for all 6 handlers
- [x] No security regressions (keys not logged, not in lists)
- [x] `json:"-"` on WgServer.PrivateKey preserved