Commit Graph

39 Commits

Author SHA1 Message Date
Alphaeus Mote 39b39740a3 feat(ui): replace the notifications bell with an About dialog
The bell rendered hard-coded template data ("Roman Joined the Team!",
"New Payment received") — a demo artifact that had nothing to do with the
product and no backing feature.

In its place, an About dialog reports the running server's build: version,
build time, and commit, read from GET /api/v1/version, with a copy button so
the exact build can be quoted in a bug report without shelling onto the host.
That probe predates the {success,data} envelope and returns bare snake_case
JSON, so it is fetched directly rather than through the api client, accepting
either shape in case it is ever normalised. Dev builds ("dev"/"unknown")
degrade to a readable "—" rather than an invalid date.

Removing the bell also stranded three other unreferenced template files, so
Notification.tsx, AppLinks.tsx, QuickLinks.tsx and their shared data.ts (fake
users, chat/ecommerce app links) are deleted with it.

Also fixes the account button announcing itself to screen readers as
"show 11 new notifications".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 20:55:27 -04:00
Alphaeus Mote e0b002975f feat(api-docs): require auth for docs and add filterable route discovery
The OpenAPI spec and Swagger UI were public. Put them behind the same
authentication as the rest of the API, and add a compact route list so a
client can ask "what can I call?" without opening dev tools.

Access:
- /api/openapi.json and /api/routes require a bearer token or API key.
- /api/docs additionally accepts a session cookie set at login, so a
  signed-in operator can open the docs in a new tab; an anonymous browser
  is redirected to /login?redirect=... and returned afterwards.
- The cookie is HttpOnly and path-scoped to /api/docs, so it is never sent
  to /api/v1/* and cannot authenticate an API call (no CSRF surface).
  Verified: cookie-only request to /api/v1/rules returns 401.

Discovery: both the spec and GET /api/routes accept ?method=get,post and
?path=<substring> (comma-separated, case-insensitive). The route list
returns method, path, summary, tag, public, and `allowed` — false when a
read-scoped API key cannot invoke that route. /api/docs passes the same
query through to the spec it loads.

UI: a </> icon in the header (both layouts) and an Administration → API
Docs menu entry, opened in a new tab via a new `external` nav-item flag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 10:44:54 -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 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 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 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 4f949e6d8f fix(auth): make API keys actually authenticate; add read/read-write scopes
API keys were never validated — the middleware only checked session tokens,
so an X-API-Key request always 401'd. Add auth.Service.ValidateAPIKey (looks
up the key hash, enforces enabled/revoked/expiry, loads the user + roles,
stamps last_used_utc) and route X-API-Key / bearer auth through it.

Add per-key scopes (migration 006): "read" (GET/HEAD only) or "readwrite"
(full access, default). The middleware rejects mutating requests from a
read-scoped key with 403. Create accepts a scope; list and create responses
include it; the UI create dialog has a scope selector and the list shows a
scope chip. Disable/re-enable and revoke (permanent) were already correct.

Verified live: RW key GET/POST ok; read key GET ok, POST 403; disable→401,
re-enable→200; revoke→401 and re-enable blocked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 19:01:30 -04:00
Alphaeus Mote 8ee9b95cde feat(ui): make dashboard widgets drill in
Count tiles link to their resource pages; the run-stat cards open Activity,
Recent Rule Runs opens Rule Runs, and Connection Health opens Connections.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 18:25:15 -04:00
Alphaeus Mote 154cadc792 feat(ui): per-rule history dialog showing objects added/removed
Add a History icon to each rule that opens a dialog listing the actual
objects this rule acted on — added, removed, moved — scoped to the rule via
the activity feed's ruleId filter, with category/result filters, paging, and
the per-action detail drill-in. Colour a "Completed" last-run result as
success (not amber) now that the rules list surfaces it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 17:48:28 -04:00
Alphaeus Mote 50147f357f feat(ui): show schedule + next run on the rules list
Add a Schedule column to the rules table that resolves each rule's
scheduleId to the schedule name and its next run time (or "Manual"),
pairing with the newly seeded built-in schedules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 17:14:56 -04:00
Alphaeus Mote 4c20fe1e15 feat(ui): live attribute + value pickers in the filter builder
The filter builder's attribute field now searches the selected connection's
full directory schema (scoped to the rule's object type) instead of a fixed
curated list, and the value field suggests the distinct values actually
present in the directory for the chosen attribute — both search-as-you-type
with the curated common attributes still shown first.

New AttributePicker and ValuePicker components (async MUI autocompletes over
ConnectionsApi.attributes / attributeValues), wired into each condition row;
memberOf still uses the group picker and raw-LDAP keeps a plain field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 15:58:02 -04:00
Alphaeus Mote e513687b5f feat(ui): dynamic-group rule editor
Replace the old read-only rule form (which could only edit scalar metadata
and showed "author via config import" for conditions/actions) with a full
tabbed editor that authors the whole rule:

- Scope: connection, object type, and a searchable base-OU picker.
- Filter: a condition-group builder with attribute autocomplete (from the
  backend metadata), operator dropdowns, per-condition/-group NOT, AND/OR
  join within and across groups, and a raw-LDAP escape hatch. memberOf
  operators render a group picker for the value.
- Target & action: choose the action (Sync membership to group / Move to OU
  / Ensure group exists / Add to group), pick or paste the target group/OU,
  set the sync mode (Full / Managed / Add-only) and create-if-missing;
  multiple actions supported.
- Schedule: run manually, on an existing schedule, or create an interval or
  cron schedule inline.
- Preview: live dry-run against the directory (POST /rules/preview) showing
  match count, generated filter, planned +add/-remove, and sample matches.

New DirectoryPicker (search-or-type Autocomplete backed by the connection
directory endpoint) is reused for base OU, target group, target OU, and
memberOf values. API layer gains RuleMetadata/DirectoryObject/RuleInput
types and RulesApi.metadata/previewSpec + ConnectionsApi.directory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 15:19:30 -04:00
Alphaeus Mote e74cb454c8 feat(activity): add action-ledger intelligence and drill-in feed
Turn the rule_run_actions ledger into operator intelligence. A new
ActivityService rolls the ledger up by time window (24h / 7d / all-time)
into syncs, operations and removals with success/failure counts and the
number of distinct objects affected, plus all-time totals per action type
and a most-active-rules ranking. A companion filtered, paginated feed
answers the operational questions directly: what action ran, what
happened, to which object, triggered by whom, and when.

Backend:
- ActivityService.Summary() and ListActions(filter) over the joined
  rule_run_actions / rule_runs / rules tables, categorising each action
  type as Sync (AddToGroup/AddGroupToGroup), Removal
  (RemoveFromGroupIfNoLongerMatched) or Operation (everything else).
- GET /api/v1/activity/summary and GET /api/v1/activity (category,
  actionType, status, ruleId, search, pagination).
- Table-driven test seeding a run with mixed action types/statuses and
  asserting window roll-ups, distinct-object counts, top rules, and the
  category/status feed filters.

Frontend:
- New Activity page: window summary cards, by-action-type and
  most-active-rules tables, and a drill-in feed with category/result/
  object filters and a detail dialog that pretty-prints the action's
  details JSON and error.
- Wired into the vertical sidebar and horizontal navbar under Automation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 14:09:04 -04:00
Alphaeus Mote 6cb8e67c0c feat(ui): remove language selector from header
Drop the flag/language dropdown from both the vertical and horizontal
headers and delete the now-unused Language component. OrchestrAD ships a
single language, so the selector was dead UI chrome.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 14:08:44 -04:00
Alphaeus Mote f0c81dfa51 feat(ui): Security page (OIDC + TLS config) and canonical name in preview
Add a Security admin page wiring the OIDC and TLS backends: an SSO/OIDC form
(issuer, client id/secret, redirect, scopes, claim mappings, default role) and a
TLS card showing the live certificate and a source picker - self-managed,
bring-your-own (PEM upload), or a Windows-store certificate (enumerate + select).
Add OidcApi/TlsApi clients + types, a Security nav entry, and a Canonical Name
column to the rule preview.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 13:06:30 -04:00
Alphaeus Mote 5674ca7849 feat(ui): dark-by-default, OrchestrAD branding, de-jarred login, SSO button
Default the theme to dark (toggle still available). Rebrand the logo to the
OrchestrAD icon + wordmark. Redesign the login into a calm, centered card on a
soft themed backdrop (removed the 3D character illustration and decorative
circles). Add a 'Sign in with SSO' button shown when OIDC is enabled, and adopt
the OIDC callback token from the URL fragment (hydrating the user via /auth/me).
Replace the hardcoded 'Mike/Admin' sidebar card with the real signed-in user and
a working sign-out; de-jar the search label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 12:59:14 -04:00
GraceSolutions 611f736088 feat(auth): default admin/admin bootstrap with forced first-login password change
- Add password_reset_required column (migration 004) + repository support
- auth.Service.ChangePassword verifies current, hashes new, clears flag,
  emits PasswordChange audit events for success and failure
- Bootstrap: when no ORCHESTRAD_BOOTSTRAP_PASSWORD[_FILE] is set, seed
  admin/admin with password_reset_required=true and log a one-time warn
  banner; env/file-supplied passwords keep the flag clear
- Expose passwordResetRequired in UserInfo / /auth/me / login response
- POST /api/v1/auth/change-password behind the authenticated group
- Frontend: /change-password page + ChangePasswordForm, AuthLogin and
  RequireAuth bounce any other route to it while the flag is set
- Docs: DesignSpecification 8.6/8.8 and Template 7.6/7.7 rewritten,
  Trusted Proxy renumbered to 7.8 in the template, acceptance items
  updated to match the new default-credential behavior
2026-04-23 17:36:23 -04:00
GraceSolutions 329825ce86 fix(auth): sanitize redirect, read token from storage, 301 legacy /auth/* paths
- Add sanitizeRedirect/safeRedirectTarget helper; reject anything that isn't
  a safe local path (must start with a single /, no scheme, no whitespace,
  not /login itself). Apply in RequireAuth when encoding the current pathname
  and in AuthLogin when consuming ?redirect=.
- Make configureApi's getToken read localStorage directly via readCurrentToken
  so the first request after login cannot race the AuthContext re-render that
  previously owned the token via a React closure.
- Redirect legacy /auth/* (including the pre-flatten /auth/auth1/login) with
  HTTP 301 to /login in the webui handler so stale bookmarks can't seed the
  SPA router with a malformed URL.
- Regression test TestHandler_LegacyAuthPathRedirectsToLogin covering four
  legacy path shapes.
2026-04-23 17:12:41 -04:00
GraceSolutions c583a00cc1 fix(frontend): drop hardcoded localhost:8080 fallback from API client
getApiBaseUrl returned `http://localhost:8080` whenever window was
undefined, which meant the Next.js static export baked that string into
every chunk that could be prerendered (notably 3056-*.js and the
/login page chunk). A production binary served from any other host or
port still contained the literal string, which would surface in
developer-tooling searches and could misroute fetches in edge cases.

Return an empty string as the SSR fallback and teach buildUrl to
produce a relative URL (path + query only) when the base is empty. The
browser's fetch then resolves against the current origin, which is the
right answer for the single-binary same-origin deployment regardless
of scheme, host, or port.

Verified with a clean frontend/out rebuild: all 22 JS chunks loaded
from /login are now free of localhost:8080 and /auth/auth1/login; the
admin login POST continues to return 200 with a valid session token.
2026-04-23 16:48:25 -04:00
GraceSolutions b9091db98d refactor(frontend): flatten /auth/auth1/login to /login and use same-origin API
Two coupled frontend cleanups:

- The Spike template routed login through /auth/auth1/login, a leftover
  from the multi-variant demo layout. Move the page to /login and
  update every reference (header menu, sidebar, AuthContext redirects,
  RequireAuth redirects). Any deep links to the old path still resolve
  via the SPA fallback in the embedded webui handler.

- The API client hardcoded http://localhost:8080 as the base URL, which
  meant the built frontend could only talk to a dev-mode backend on a
  specific port. Replace with window.location.origin so the same
  compiled bundle works regardless of scheme, host, or port; the single
  binary serves both UI and API from one listener, so same-origin is
  always correct for production deployments.
2026-04-23 16:40:48 -04:00
GraceSolutions e396094b47 refactor(frontend): flatten Spike template to OrchestrAD-only surface
Prune the Spike NextJS PRO demo content that was still shipping inside
the embedded UI and rename the route group to match the app, so every
page we compile is one we actually use. Separately the full Spike main
is preserved at Grace-Solutions/Spike-NextJS-PRO-Template on a parallel
branch for future template pulls.

Route group
- Rename src/app/(DashboardLayout) -> src/app/(app); update all
  imports, lazy chunk references, and layout boundary names.

Remove demo routes
- src/app/(app)/{apps,charts,muicharts,forms,icons,mui-trees,
  react-tables,tables,theme-pages,ui-components,widgets,sample-page,
  dashboards} and the remaining (app)/apps/{blog,ecommerce,invoice}
  detail/edit subtrees.
- src/app/{frontend-pages,landingpage} and the blog [slug] route.
- src/app/auth/{auth2,error,maintenance} and the auth1 forgot/register
  variants; keep the primary login flow only.
- src/app/api/* demo fetchers (blog, chat, contacts, dashboard,
  eCommerce, email, invoice, kanban, notes, ticket, userprofile,
  globalFetcher); real calls go through @/lib/api.

Remove demo components and contexts
- src/app/components/{apps,dashboards,forms/form-*,pages,widgets,...}.
- src/app/context/{BlogContext,ChatContext,Ecommercecontext,...};
  keep AuthContext, CustomizerContext, Config only.
- src/app/types/{apps,auth}; AuthLogin now uses a local props type.

Layout cleanup
- (app)/layout/vertical/header/Header.tsx and horizontal/header
  drop ProductProvider / Ecommerce wrappers so the build succeeds.
- (app)/layout/horizontal/navbar/Menudata.ts mirrors the OrchestrAD
  sidebar MenuItems so both layouts expose the same routes.

Build artifacts
- Re-stage frontend/out into backend/internal/webui/dist after the
  flatten; index.html now references the (app) chunk graph.

Binary impact (windows/amd64, CGO off): ~37.5 MB -> 26.27 MB.
Embedded dist: 298 files / 14.46 MB.
2026-04-23 15:05:19 -04:00
GraceSolutions 2dde5af6cb feat(ui-embed): ship the web UI inside the Go binary
Switch Next.js to static export (output: 'export', trailingSlash: true) and add a new backend/internal/webui package that embeds frontend/out/ via //go:embed. The backend now serves the UI from its own HTTP server with SPA fallback, long-lived cache headers on _next/static/*, and no dependency on a separate Node.js runtime or static host.

- frontend/next.config.mjs: output='export', trailingSlash=true, images.unoptimized.

- backend/internal/webui: Handler() with SPA fallback, resolve() mirroring Next trailing-slash behavior, IsBuilt() helper, and a placeholder dist/index.html so go build works without a prior frontend build. Top-level .gitignore tracks only the placeholder and its own .gitignore; the copied static export is ignored.

- backend/internal/server/server.go: mount webui.Handler() as the chi NotFound handler so /api/v1/* and /health continue to be served by their handlers while all other routes resolve through the embedded UI with SPA deep-link support.

- scripts/build.ps1: build the frontend (npm install if needed, then npm run build) before any Go build, stage frontend/out into backend/internal/webui/dist, and fail loudly if the UI output is missing or empty. Adds -SkipFrontend for developer iteration.

- Remove Spike demo content that prevented static export: api/* route handlers (dynamic POST/PUT/DELETE), apps/{blog,ecommerce,invoice} dynamic [slug]/[id] detail/edit pages, and frontend-pages/blog/[slug].

- Fix TypeScript errors surfaced by enabling the production build: ApiMeta.totalCount (not total) in audit and rule-runs pages; MUI v7 Grid uses size={{...}} instead of item+xs+md in config page.

Binary size grows from ~8 MB to ~37 MB, reflecting the embedded UI. The produced single binary is now sufficient to run the full product; no separate web server is required.
2026-04-23 14:48:59 -04:00
GraceSolutions 9d974e9cb2 feat(ui): config import/export page
Add /config with an Export card that downloads the current configuration as a pretty-printed JSON file (orchestrad-config-<timestamp>.json) and an Import card that parses a chosen file, shows a per-entity chip summary, and offers Validate (dry run) and Apply Import. Results render in an ImportReportView with created/updated/skipped totals, per-entity counts, and warnings/errors surfaced from the backend. Expand ConfigApi.import to send { payload, dryRun } in the JSON body per the server contract and add ConfigExport / ImportReport / ImportEntityReport and related RuleExport/etc. types mirroring services.ConfigExport.
2026-04-23 14:31:26 -04:00
GraceSolutions a7a98aa344 feat(ui): application settings admin page
Add /settings with sorted key/value list, type chip, description, sensitive badge, and updated timestamp. SettingFormDialog PUTs /settings/{key} for create/edit; key is locked when editing. Sensitive values come back masked from the API, so the dialog warns the user to re-enter the value and switches to a password input when isSensitive is toggled on. JSON values get a multiline textarea.
2026-04-23 14:28:40 -04:00
GraceSolutions 0751f876f5 feat(ui): audit log browser
Add /audit page with server-side pagination and the full filter set supported by the backend (event type, resource type, action, username, outcome, start/end UTC). Table shows time, event chip, action, user, resource, outcome chip. AuditEventDialog pulls /audit/{id} and renders metadata (time, component, user, IP, user agent), any error message, and a pretty-printed JSON view of details. Extend AuditApi.list with a full AuditFilter type and add AuditApi.get.
2026-04-23 14:27:40 -04:00
GraceSolutions 75fc291d50 feat(ui): api keys admin page
Add /api-keys with user-scoped listing (defaults to current user, admin can select any user). Columns: name, key prefix, status chip (Active/Revoked/Expired), enabled toggle, created, last used, expires. Per-row enable/disable, revoke, delete. ApiKeyCreateDialog posts to /api-keys and displays the one-time plaintext key with a copy-to-clipboard affordance; closing is only allowed via the Done button once the key is shown so it cannot be missed by an accidental backdrop click.
2026-04-23 14:26:34 -04:00
GraceSolutions ec4aa25e62 feat(ui): users admin page
Add /users list (username, display name, email, local/OIDC source, last login, active toggle) with per-row edit/delete. UserFormDialog supports create (password required) and edit (password optional, username locked for OIDC users). Update via PUT allows toggling active status and changing password.
2026-04-23 14:24:56 -04:00
GraceSolutions 70c5de24ed feat(ui): rule runs history page with detail dialog
Add /rule-runs list with server-side pagination, per-rule filter (uses /rules/{id}/runs when set), and client-side status filter. Columns: rule name, status chip, execution mode, started, duration, matched/processed, actions (ok/fail), triggered by. RuleRunDetailDialog loads /rule-runs/{id} (which includes action records) and renders run stats, any run-level error message, and a per-action table with status, type, target DN, duration, and error/details. Add RuleRunAction and RuleRunDetail types and update RuleRunsApi.get to return the detail shape.
2026-04-23 14:23:32 -04:00
GraceSolutions c257b83de1 feat(ui): rules management page with preview and run
Add /rules page with list view (object type, condition/action counts, enabled toggle, last run + result chip) and per-row preview/run/edit/delete/enable actions. RuleFormDialog covers top-level fields the API supports (identity, AD connection, object type, base DN / scope overrides, execution mode, schedule, group join operator, max parallelism, stop-on-error). Condition groups and actions are rendered read-only (authored via config import today). RulePreviewDialog invokes POST /rules/{id}/preview and renders the generated LDAP filter, warnings, matched DNs, and planned actions with change indicators. Add RulePreviewResult types and type RulesApi.preview accordingly.
2026-04-23 14:21:21 -04:00
GraceSolutions b07a46ef4f feat(ui): schedules management page
Add /schedules page with list view (name, kind, definition summary, timezone, enabled, next run) and create/edit/delete/enable-disable actions. ScheduleFormDialog supports both Easy (interval + Minutes/Hours/Days) and Cron (six-field expression) kinds with UTC/Local timezone selection, matching the backend ScheduleRequest/Response shape.
2026-04-23 14:17:51 -04:00
GraceSolutions 999415f942 feat(ui): AD connections management page
Add /connections page with list view (hosts:port, root DN, TLS mode, enabled toggle, last test result) and per-row test/edit/delete actions. ConnectionFormDialog covers the full LDAP surface (hosts, port, TLS/StartTLS/invalid certs, root DN, optional bind DN, credential binding, search scope, paging). ConnectionTestDialog invokes the server-side test and renders each step (TCP, bind, root DN access) with latency. Add JSON tags to services.TestResult/TestDetail so the camelCase wire format matches the frontend ConnectionTestResult type.
2026-04-23 14:10:46 -04:00
GraceSolutions caaa890d75 feat(ui): credentials management page with test-bind dialog
Align frontend types with the Go backend payload shape (createdAt/updatedAt/lastTestedAt naming, CredentialTestResult). Add a typed CredentialsApi with CRUD + enable/disable + test. Add /credentials page with a data table showing name, type, username, enabled toggle, last test time, and last result, plus per-row actions (test, edit, delete). Add CredentialFormDialog for create/edit (leaving password blank preserves the stored secret). Add CredentialTestDialog that performs a live LDAP bind against a user-specified host/port/TLS combination and surfaces connect/bind latency. Extract shared formatDateTime/formatDurationMs/formatLatencyNs helpers into lib/format.ts. Trim the Spike template's orphan menu entries from MenuItems.ts.
2026-04-23 14:07:40 -04:00
GraceSolutions 617d6370b5 feat(ui): dashboard summary page, OrchestrAD sidebar, real profile menu
Replace the Spike demo dashboard with a live view backed by /api/v1/dashboard/summary: entity count tiles, 24h/7d run stats, recent rule runs, and connection health. Rebuild the vertical sidebar navigation around OrchestrAD's actual sections (Rules, Schedules, Rule Runs, Connections, Credentials, Users, API Keys, Audit Log, Settings, Config). Wire the header profile dropdown to the current session, showing the logged-in user's name/role/email and a working Log out button. Align DashboardSummary TypeScript shape with the Go backend payload (CountPair counts, ruleRunStats, recentRuns, connectionsHealth).
2026-04-23 13:53:31 -04:00
GraceSolutions e08bbb2fba feat(ui): wire frontend auth and typed api client
Add a typed fetch wrapper that unwraps the backend envelope, attaches Bearer tokens, and normalizes errors. Introduce resource-specific API helpers for every management endpoint. Ship AuthProvider that persists the session to localStorage and exposes login/logout. Wrap the (DashboardLayout) subtree in a RequireAuth guard and replace the demo AuthLogin form with one that calls /api/v1/auth/login and honors a redirect query param. Include docs/FrontendCleanup.md describing the Spike template layout, what to keep, and what to prune.
2026-04-23 13:48:30 -04:00
GraceSolutions 8986fc9325 chore: Flatten frontend, remove figma/docs (88MB saved)
- Moved main package contents to frontend root
- Removed figma-file directory (88MB)
- Removed docs directory
- Removed unused package variants
2026-04-19 10:22:23 -04:00
GraceSolutions 9acf3b8289 Merge commit '1652dad4f7b69d8375596d27e514513e4a970470' as 'frontend' 2026-04-19 10:20:39 -04:00
GraceSolutions 65dc1e15a4 chore: Remove scaffold frontend, will use Spike template via subtree 2026-04-19 10:20:24 -04:00
GraceSolutions 46fc0409ad feat: Add Next.js 14 frontend scaffold
- Next.js 14 with App Router
- TypeScript strict mode
- Tailwind CSS with dark mode support
- React Query for server state
- NextAuth.js integration ready
- Dashboard layout with sidebar navigation
- API client with error handling
- Core type definitions for all entities
- Utility functions for dates and classnames
2026-04-19 10:19:40 -04:00