Release: object viewer, roles, cert/firewall automation, API key fix #12

Merged
gsadmin merged 11 commits from development into main 2026-09-03 02:26:20 +00:00

11 Commits

Author SHA1 Message Date
Alphaeus Mote 35d8b81c91 fix(api-keys): scan created_utc as a string in List (modernc timestamp)
APIKeyService.List scanned created_utc straight into time.Time, which the
modernc.org/sqlite driver returns as a string — surfacing as a 500 "Failed
to list API keys". Scan it into a string and parse. Regression test covers
the create+list round-trip (created_utc parsed, scope preserved).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 22:14:26 -04:00
Alphaeus Mote fbb308640c feat(ui): paginate long result lists
Add client-side pagination (TablePagination) to lists that could grow long
and cause endless scroll:
- Object Viewer search results
- Object attribute detail dialog
- Windows certificate store list (Security)
- Rule preview matched objects (previously hard-capped at 100 with no paging)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 22:08:51 -04:00
Alphaeus Mote 6587905eeb fix(ldap): decode objectGUID/objectSid and binary attributes for display
The object viewer showed raw bytes for binary attributes. Format them for
display: objectGUID as a canonical GUID, objectSid/sIDHistory as S-1-… SID
strings, and any other non-printable value as base64. Applied in the
query-preview path that the object viewer uses; printable values pass through.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 22:01:34 -04:00
Alphaeus Mote 13b336a77e feat(connections): LDAPS port auto-flip + skip-cert default; keep 3 backups
- Toggling LDAPS in the connection form now auto-sets the port (636 on / 389
  off when it's still the other default) and enables "Allow invalid certs",
  because a non-domain-joined host usually can't validate the DC's LDAPS
  certificate. This fixes the common "existing connection was forcibly
  closed" seen when LDAPS was enabled while the port stayed 389 (dialing TLS
  to the plaintext port). Helper text explains the traffic is still encrypted.
- LDAP client sets tls ServerName to the host so verification succeeds when a
  DC cert IS trusted (ignored under InsecureSkipVerify).
- Backups retention reduced from 10 to 3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 22:01:34 -04:00
Alphaeus Mote 2befe64a0c feat(install): idempotent Windows firewall rule; skip the blank MSI EULA
Firewall:
- On service initialize/install, create an idempotent inbound allow rule
  ("OrchestrAD") for the configured listen port, scoped to RFC 1918 private
  ranges plus CGNAT (10/8, 172.16/12, 192.168/16, 100.64/10). The rule is
  deleted-then-added so it always reflects the current port, and removed on
  service uninstall. Best-effort (needs admin; the MSI custom action and
  service run elevated); no-op off Windows. Verified the netsh rule lands
  with the expected port and remote-address scoping.

MSI:
- Skip the license/EULA page (Welcome now goes straight to the install
  directory), since it was blank. A standard short notice is kept in
  license.rtf only so the stock license control resolves at build time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 21:46:08 -04:00
Alphaeus Mote 27ff00d75c feat(tls): install self-managed CA into the Windows trust stores
When TLS is in auto (self-managed) mode, install the generated root into the
LocalMachine "Root" (Trusted Root CAs) store and the intermediate into the
"CA" (Intermediate CAs) store, so clients on this host trust the served
chain without manual import. Runs on every ensure/renewal with a replace
disposition, so it is idempotent and a renewed CA supersedes the previous
one. Best-effort (needs admin; the Windows service runs as LocalSystem);
a no-op on non-Windows.

Verified: OrchestrAD Root CA appears in LocalMachine\Root and the
Intermediate in LocalMachine\CA after startup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 21:36:19 -04:00
Alphaeus Mote b2218f6be4 feat(ui): Object Viewer — browse & inspect directory objects to build filters
A new Object Viewer page: pick a connection, choose an object type and search
by name (or drop in a raw LDAP filter and a search base), list the matches,
and drill into any object to see all its attributes with copy buttons for the
attribute name and value — so operators can discover the exact attributes and
values to put in a rule filter.

Built on the existing query-preview endpoint (now typed as QueryPreviewResult);
the detail view requests all attributes (["*"]). Added to the Directory nav.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 21:32:51 -04:00
Alphaeus Mote 6fdf9a9d54 feat(users): assign RBAC roles to users; OIDC default-role dropdown + clearer SSO config
Roles:
- Add GET /api/v1/roles (built-in SuperAdmin/Admin/Operator/Viewer) and
  wire role assignment into user create/update (UserRepository.SetRoles /
  GetRoleNames / ListRoles). User responses now include roles.
- User dialog gains a roles multi-select; the users list shows role chips.

OIDC / SSO config UI:
- Default role is now a dropdown populated from /roles.
- Issuer URL shows real provider examples (Entra/Okta/Google).
- Replace the confusing manual "Redirect URL" field with a read-only,
  auto-derived callback URL (from the browser origin / public URL) plus a
  copy button — the exact value to register at the IdP. The backend still
  auto-derives the callback and honors an env override.

Verified: /roles lists the four roles; creating/updating a user with roles
round-trips through GET.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 21:25:59 -04:00
Alphaeus Mote 069915415c feat(api): document request bodies, params, and auth in the OpenAPI spec
Make the API browsable/usable from Swagger UI without dev tools:
- Normalize chi's trailing slash on collection roots (Post("/")) so registry
  detail and pagination attach — previously POST /ad-connections etc. showed
  no request body.
- Document request bodies for the main create/update operations (connections,
  credentials, schedules, api-keys, users, settings, tls mode/certificate,
  query-preview, config import) with component schemas.
- Add standard page/pageSize query params to collection GETs.
- Add the X-API-Key security scheme alongside bearer so both auth methods
  show in the Authorize dialog.

Test covers the trailing-slash normalization + body attachment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 21:06:33 -04:00
Alphaeus Mote 12ef83976d fix(ui): auto-list Windows store certificates when that source is selected
The Windows-store certificate list only loaded after clicking a separate
"List certificates" button, so selecting the Windows-store option appeared
to show nothing. Fetch the certificates automatically when the source is
chosen (and the store is supported); the button becomes a Refresh. The
backend endpoint and windowsStoreSupported flag were already correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 21:06:33 -04:00
Alphaeus Mote d3756bce80 feat(db): store the database under data/db and auto-migrate existing files
The SQLite database now lives at data/db/orchestrad.db instead of the data
root. db.New creates the db/ directory (SQLite will not) and, on first run,
moves a legacy data/orchestrad.db plus its -wal/-shm sidecars into db/ so
existing installations keep their data. Verified live: an existing demo
database migrated into data/db and all data (connections, rules, schedules)
was retained. Test covers the move + idempotency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 20:41:34 -04:00