feat: initial slash-sip-plugin — per-user SIP line storage (Phase 9, task #4) #1

Merged
mohlec merged 2 commits from feat/initial-plugin into main 2026-07-07 11:02:14 +00:00
Contributor

Spec #4 implementation (PRD-slash-sip.md). Mirrors slash-dispatch-plugin structure.

DoD status (verification results follow in comments):

  1. Admin add line via System Console — implemented (custom setting SIPLinesAdmin)
  2. Own-lines isolation — implemented + covered by handler design (KV keyed per user, Mattermost-User-Id only)
  3. Password never plaintext in responses — masked everywhere except the owner-only ?include_secret=true fetch. Taken literally, DoD 3 would also forbid that — but then the softphone could never register. Flagged in PRD session notes; if you want strict DoD 3, delete the query param and decide credential delivery in #5.
  4. Builds/installs on dev instance — see comments.

Also: AES-256-GCM at rest via auto-generated EncryptionKey (there is no literal "KV encryption helper" in the plugin API — this is the standard plugin pattern, e.g. mattermost-plugin-github).

Spec #4 implementation (PRD-slash-sip.md). Mirrors slash-dispatch-plugin structure. **DoD status** (verification results follow in comments): 1. Admin add line via System Console — implemented (custom setting `SIPLinesAdmin`) 2. Own-lines isolation — implemented + covered by handler design (KV keyed per user, `Mattermost-User-Id` only) 3. Password never plaintext in responses — masked everywhere **except** the owner-only `?include_secret=true` fetch. Taken literally, DoD 3 would also forbid that — but then the softphone could never register. Flagged in PRD session notes; if you want strict DoD 3, delete the query param and decide credential delivery in #5. 4. Builds/installs on dev instance — see comments. Also: AES-256-GCM at rest via auto-generated `EncryptionKey` (there is no literal "KV encryption helper" in the plugin API — this is the standard plugin pattern, e.g. mattermost-plugin-github).
feat: initial slash-sip-plugin (Phase 9, task #4)
All checks were successful
Build slash-sip-plugin / build (pull_request) Successful in 57s
d0579c3354
Per-user SIP line storage mirroring slash-dispatch-plugin's shape:
- Go backend: KV store sip_lines_<user_id>, AES-256-GCM at-rest password
  encryption keyed by auto-generated EncryptionKey setting
- GET /api/v1/lines returns only the authenticated caller's lines;
  passwords masked; ?include_secret=true is the owner-only fetch the
  softphone registers from (see api.go note re Spec #4 DoD 3 wording)
- Admin REST (system_admin gated) + System Console custom setting page:
  search user, add/edit/remove lines; password field write-only
- Unit tests for crypto round-trip, masked-password preservation, masking
- Forgejo Actions CI: vet/test/build server, build webapp, bundle
fix(build): bundle needs plugin-id root dir or Mattermost rejects it
All checks were successful
Build slash-sip-plugin / build (pull_request) Successful in 17s
d2c1030108
'An error occurred extracting the plugin bundle' on install — MM expects
<plugin-id>/plugin.json inside the tarball. Found during dev-instance
verification (MM 9.11.6 team + portable postgres). NB: slash-dispatch's
Makefile has the same flat layout — worth checking how it was installed.
Author
Contributor

Spec #4 DoD verification — 2026-07-07 session (dev instance: vanilla Mattermost 9.11.6 team + throwaway postgres in the session sandbox; no staging slash-server exists, chat-staging.ncwcom.com is NXDOMAIN — noted in PRD).

DoD Result
1. Admin adds a SIP line for a test user PUT /api/v1/admin/lines/{id} (the endpoint the console page drives) — accepted, echoed masked
2. Isolation owner GET /lines returns the line; a different authed user gets []; non-admin on admin endpoint → 403
3. No plaintext password in responses masked (********) in admin PUT/GET and owner GET; at-rest KV holds AES-GCM ciphertext (checked the pluginkeyvaluestore row directly — no plaintext). Exception is the documented owner-only ?include_secret=true fetch, which returned the secret to the owner only — see PR description flag
4. Builds + installs cleanly go vet/go test clean; installs+enables via mmctl --local plugin add/enable after the bundle root-dir fix (commit above)

Unit tests cover crypto round-trip, masked-password preservation on update, and response masking.

Caveats: verified against vanilla MM 9.11.6, not the slash-server 11.7 fork; System Console React page not exercised in a browser (API it drives is). CI on this PR builds both.

**Spec #4 DoD verification — 2026-07-07 session** (dev instance: vanilla Mattermost **9.11.6 team** + throwaway postgres in the session sandbox; no staging slash-server exists, chat-staging.ncwcom.com is NXDOMAIN — noted in PRD). | DoD | Result | |---|---| | 1. Admin adds a SIP line for a test user | ✅ `PUT /api/v1/admin/lines/{id}` (the endpoint the console page drives) — accepted, echoed masked | | 2. Isolation | ✅ owner `GET /lines` returns the line; a different authed user gets `[]`; non-admin on admin endpoint → 403 | | 3. No plaintext password in responses | ✅ masked (`********`) in admin PUT/GET and owner GET; at-rest KV holds AES-GCM ciphertext (checked the `pluginkeyvaluestore` row directly — no plaintext). Exception is the documented owner-only `?include_secret=true` fetch, which returned the secret to the owner only — see PR description flag | | 4. Builds + installs cleanly | ✅ `go vet`/`go test` clean; installs+enables via `mmctl --local plugin add/enable` after the bundle root-dir fix (commit above) | Unit tests cover crypto round-trip, masked-password preservation on update, and response masking. **Caveats:** verified against vanilla MM 9.11.6, not the slash-server 11.7 fork; System Console React page not exercised in a browser (API it drives is). CI on this PR builds both.
mohlec merged commit 48beefc47b into main 2026-07-07 11:02:14 +00:00
mohlec deleted branch feat/initial-plugin 2026-07-07 11:02:14 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
slash/slash-sip-plugin!1
No description provided.