Commit e93d5be
feat(admin): three-mode auth — BUZZ_ADMIN_AUTH enum + NIP-98 pubkey allowlist
Deletes BUZZ_ADMIN_INSECURE_NO_AUTH. Replaces it with BUZZ_ADMIN_AUTH, a
mode enum with three exact values:
- unset / "token" — bearer token via BUZZ_ADMIN_TOKEN (unchanged default)
- "disabled" — no auth; boot WARN retained (replaces INSECURE_NO_AUTH)
- "nip98" — NIP-98 HTTP Auth via BUZZ_ADMIN_PUBKEYS allowlist
All existing token/disabled invariants carry 1:1 under the new name.
Junk values fail closed at startup with a ConfigError.
NIP-98 mode (admin-moderation scope):
- Parses BUZZ_ADMIN_PUBKEYS as comma-separated 64-hex pubkeys (deduped).
- BUZZ_ADMIN_PUBKEYS required non-empty in nip98 mode; warn-and-ignore in
token/disabled modes. BUZZ_ADMIN_TOKEN + nip98 = ConfigError.
- authorize_nip98(): single Authorization: Nostr <base64 event> header,
verify_nip98_event, deployment-scoped replay guard (admin-moderation),
allowlist membership check. Uniform 401 on all failures; no oracle.
- WWW-Authenticate: Nostr on 401 (Bearer stays in token mode) — the SPA
uses this header to discover the auth mode.
- Canonical URL: https://<BUZZ_ADMIN_HOST>/api/admin/v1<stripped-path>;
http:// for loopback hosts (local dev). Axum strips the prefix before
handlers; ADMIN_API_PREFIX constant re-adds it for NIP-98 verification.
SPA (admin-web):
- probeAuthMode() reads WWW-Authenticate: Bearer/Nostr/absent to return
"token" | "nip98" | "disabled".
- nip98 mode: signNip98() helper builds kind-27235 events via window.nostr
(NIP-07); send() attaches Authorization: Nostr per request.
- Nip07Screen: shown when nip98 mode is detected but window.nostr is absent;
instructs operator to install nos2x or Alby.
- 401 in nip98 mode re-signs once then surfaces the error (no infinite loop).
Docs/config:
- docs/admin/README.md rewritten to three-mode shape; migration note from
BUZZ_ADMIN_INSECURE_NO_AUTH.
- Both .env.example files updated (root and deploy/compose/).
- CHANGELOG.md Unreleased sections updated with three-mode description.
Tests:
- Config matrix: all mode values, junk, every mutual exclusion,
missing/invalid BUZZ_ADMIN_PUBKEYS.
- NIP-98 route tests: wrong pubkey → 401, replay → 401, wrong u/method →
401, duplicate Authorization → 401, valid → 200, valid + wrong host → 403.
- Regression pins: token-mode and disabled-mode behavior unchanged.
- Playwright: nip98 mode without NIP-07 → instruction screen; mocked
window.nostr happy path signs requests and renders dashboard.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>1 parent 75277f3 commit e93d5be
11 files changed
Lines changed: 1141 additions & 195 deletions
File tree
- admin-web
- src
- tests
- crates/buzz-relay/src
- api/admin
- deploy/compose
- docs/admin
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
70 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
71 | 75 | | |
72 | 76 | | |
73 | 77 | | |
74 | 78 | | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
80 | 89 | | |
81 | 90 | | |
82 | 91 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
16 | 27 | | |
17 | 28 | | |
18 | 29 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
10 | 11 | | |
11 | | - | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
91 | 92 | | |
92 | 93 | | |
93 | 94 | | |
94 | | - | |
| 95 | + | |
95 | 96 | | |
96 | | - | |
| 97 | + | |
97 | 98 | | |
98 | 99 | | |
99 | 100 | | |
| |||
141 | 142 | | |
142 | 143 | | |
143 | 144 | | |
144 | | - | |
| 145 | + | |
145 | 146 | | |
146 | | - | |
| 147 | + | |
147 | 148 | | |
148 | 149 | | |
149 | 150 | | |
| |||
216 | 217 | | |
217 | 218 | | |
218 | 219 | | |
219 | | - | |
| 220 | + | |
220 | 221 | | |
221 | | - | |
| 222 | + | |
222 | 223 | | |
223 | 224 | | |
224 | 225 | | |
| |||
425 | 426 | | |
426 | 427 | | |
427 | 428 | | |
428 | | - | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
429 | 436 | | |
430 | | - | |
| 437 | + | |
431 | 438 | | |
432 | 439 | | |
433 | 440 | | |
| |||
468 | 475 | | |
469 | 476 | | |
470 | 477 | | |
| 478 | + | |
471 | 479 | | |
472 | 480 | | |
473 | 481 | | |
| |||
601 | 609 | | |
602 | 610 | | |
603 | 611 | | |
604 | | - | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
605 | 619 | | |
606 | 620 | | |
607 | 621 | | |
| |||
622 | 636 | | |
623 | 637 | | |
624 | 638 | | |
625 | | - | |
| 639 | + | |
626 | 640 | | |
627 | 641 | | |
628 | 642 | | |
| |||
638 | 652 | | |
639 | 653 | | |
640 | 654 | | |
641 | | - | |
| 655 | + | |
642 | 656 | | |
643 | 657 | | |
644 | 658 | | |
| |||
885 | 899 | | |
886 | 900 | | |
887 | 901 | | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
888 | 934 | | |
889 | 935 | | |
890 | 936 | | |
| |||
894 | 940 | | |
895 | 941 | | |
896 | 942 | | |
897 | | - | |
898 | | - | |
899 | | - | |
900 | | - | |
901 | | - | |
902 | | - | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
903 | 948 | | |
904 | 949 | | |
905 | 950 | | |
906 | | - | |
| 951 | + | |
907 | 952 | | |
908 | 953 | | |
909 | 954 | | |
910 | | - | |
911 | | - | |
| 955 | + | |
| 956 | + | |
912 | 957 | | |
913 | 958 | | |
914 | 959 | | |
| |||
919 | 964 | | |
920 | 965 | | |
921 | 966 | | |
922 | | - | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
923 | 972 | | |
924 | | - | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
925 | 976 | | |
926 | 977 | | |
927 | | - | |
| 978 | + | |
928 | 979 | | |
929 | | - | |
| 980 | + | |
930 | 981 | | |
931 | | - | |
| 982 | + | |
932 | 983 | | |
933 | | - | |
| 984 | + | |
934 | 985 | | |
935 | 986 | | |
936 | 987 | | |
| |||
0 commit comments