feat: add Makefile with reset-db target, update submodule refs
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
# Fix Peers API 500 + Add Delete Device to Devices List
|
||||
|
||||
## TL;DR
|
||||
> **Quick Summary**: Fix `HWID` unique constraint violation causing 500 on POST `/api/v1/peers` by making `HWID` nullable; add delete button to Devices.vue list view
|
||||
>
|
||||
> **Deliverables**:
|
||||
> - Backend: HWID model change `string` → `*string`, fix CreatePeer/CreateDevice
|
||||
> - Frontend: Delete button in Devices.vue table rows
|
||||
> - Migration: SQL to convert existing empty HWIDs to NULL + container restart
|
||||
>
|
||||
> **Estimated Effort**: Short
|
||||
> **Parallel Execution**: YES
|
||||
|
||||
## Context
|
||||
### Root Cause
|
||||
- `Device.HWID` is `string` with `uniqueIndex`. `CreatePeer` sets `HWID: ""` which collides with other devices having empty HWID → SQLSTATE 23505
|
||||
- Fix: make HWID `*string` (nullable), PostgreSQL treats NULLs as distinct in unique constraints
|
||||
|
||||
### Delete Missing
|
||||
- Backend: `DELETE /devices/:id` exists at `main.go:176`, `devicesHandler.Delete` in `devices.go:235`
|
||||
- API: `deleteDevice(id)` exists in `devices.ts:50`
|
||||
- DeviceDetail: has delete button with confirm dialog
|
||||
- Devices.vue: Actions column only has View, Config, Firewall — no Delete
|
||||
|
||||
## TODOs
|
||||
|
||||
- [ ] 1. Backend: Change HWID to `*string` in Device model
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/server-core/internal/models/models.go` line 60:
|
||||
- Change `HWID string \`gorm:"column:hwid;uniqueIndex;size:64"\``
|
||||
- To `HWID *string \`gorm:"column:hwid;uniqueIndex;size:64"\``
|
||||
|
||||
**Must NOT do**:
|
||||
- Don't change any other fields in the model
|
||||
|
||||
**Recommended Agent Profile**: `unspecified-high` (precise Go struct edit)
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Verify build after model change
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. cd apps/server-core && go build ./...
|
||||
Expected Result: No compilation errors
|
||||
Evidence: .sisyphus/evidence/task-1-build.txt
|
||||
```
|
||||
|
||||
- [ ] 2. Backend: Fix CreatePeer to not set empty HWID
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/server-core/api/peers.go` — remove `HWID: ""` line (line 96)
|
||||
- Since `HWID` is now `*string`, the zero value (nil) is correct — it won't violate unique constraint
|
||||
- Keep `RegTokenHash: ""` as-is (no unique index on that)
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Build passes after fix
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. cd apps/server-core && go build ./...
|
||||
Expected Result: Clean build
|
||||
Evidence: .sisyphus/evidence/task-2-build.txt
|
||||
```
|
||||
|
||||
- [ ] 3. Backend: Fix CreateDevice to not set empty HWID
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/server-core/api/devices.go` — verify `Create` function (line 84-89) doesn't set HWID
|
||||
- It currently doesn't set HWID at all, so with `*string` it will default to nil — correct
|
||||
- Verify `Delete` function (line 235-255) already works — it does, no changes needed
|
||||
|
||||
- [ ] 4. Migration: Convert existing empty HWIDs to NULL on server
|
||||
|
||||
**What to do**:
|
||||
- SSH into 172.20.8.191 and run SQL against the postgres container:
|
||||
```bash
|
||||
docker exec nexus-guard-suite-postgres-1 psql -U nexusguard -d nexusguard -c "UPDATE devices SET hwid = NULL WHERE hwid = '';"
|
||||
```
|
||||
- Then restart server-core container:
|
||||
```bash
|
||||
docker restart nexus-guard-suite-server-core-1
|
||||
```
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Verify empty HWIDs are now NULL
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. docker exec nexus-guard-suite-postgres-1 psql -U nexusguard -d nexusguard -c "SELECT count(*) FROM devices WHERE hwid = '';"
|
||||
Expected Result: count = 0
|
||||
Evidence: .sisyphus/evidence/task-4-sql.txt
|
||||
|
||||
Scenario: Verify POST /api/v1/peers succeeds
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. Obtain auth token via POST /api/v1/auth/login with admin credentials
|
||||
2. POST /api/v1/peers with valid body (name, wg_server_id)
|
||||
Expected Result: 201 Created (not 500)
|
||||
Evidence: .sisyphus/evidence/task-4-peers-api.txt
|
||||
```
|
||||
|
||||
- [ ] 5. Frontend: Add delete button to Devices.vue list
|
||||
|
||||
**What to do**:
|
||||
- Edit `apps/dashboard-ui/src/views/Devices.vue`
|
||||
- Add delete button in the Actions column (line 34-39), after Firewall button:
|
||||
```html
|
||||
<button @click="handleDelete(device.ID, device.Name)" class="text-red-400 hover:text-red-300 font-bold">Delete</button>
|
||||
```
|
||||
- Import `deleteDevice` from `../api/devices`
|
||||
- Add `handleDelete` function:
|
||||
```typescript
|
||||
const handleDelete = async (id: string, name: string) => {
|
||||
if (!confirm(`Delete device "${name}"? This will destroy its tunnel and all firewall rules.`)) return
|
||||
try {
|
||||
await deleteDevice(id)
|
||||
store.loadDevices()
|
||||
} catch (err: any) {
|
||||
alert(err.response?.data?.error || 'Failed to delete device')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Must NOT do**:
|
||||
- Don't remove the existing Config/Firewall buttons
|
||||
|
||||
**Recommended Agent Profile**: `visual-engineering` (Vue UI)
|
||||
|
||||
**QA Scenarios**:
|
||||
```
|
||||
Scenario: Build passes
|
||||
Tool: Bash
|
||||
Steps:
|
||||
1. cd apps/dashboard-ui && npx vue-tsc --noEmit
|
||||
Expected Result: No type errors
|
||||
Evidence: .sisyphus/evidence/task-5-tsc.txt
|
||||
```
|
||||
|
||||
- [ ] 6. Commit and push changes
|
||||
|
||||
**What to do**:
|
||||
- Commit server-core changes
|
||||
- Commit dashboard-ui changes
|
||||
- Push both submodules
|
||||
- Commit/push root submodule pointer
|
||||
|
||||
|
||||
## Success Criteria
|
||||
- [ ] `go build ./...` passes
|
||||
- [ ] `vue-tsc --noEmit` passes
|
||||
- [ ] POST `/api/v1/peers` returns 201, not 500
|
||||
- [ ] Devices.vue has a delete button per row that works
|
||||
- [ ] Existing empty HWIDs migrated to NULL
|
||||
Reference in New Issue
Block a user