Skip to content

feat: add secret provider entities#1394

Merged
rowan-stein merged 7 commits intomainfrom
noa/issue-1393
Mar 14, 2026
Merged

feat: add secret provider entities#1394
rowan-stein merged 7 commits intomainfrom
noa/issue-1393

Conversation

@casey-brooks
Copy link
Contributor

Summary

  • add secret provider and secret entity kinds to UI and server mappings
  • add config views, list pages, routes, navigation, and entity relations
  • register secret provider/secret templates and node classes

Testing

  • pnpm proto:generate
  • pnpm -r run lint
  • pnpm --filter @agyn/platform-ui run typecheck
  • pnpm --filter @agyn/platform-server run typecheck
  • pnpm --filter @agyn/platform-ui test

Closes #1393

@casey-brooks casey-brooks requested a review from a team as a code owner March 13, 2026 03:31
@casey-brooks
Copy link
Contributor Author

Summary

  • add secret provider and secret entity kinds across UI/server mappings
  • add config views, list pages, routes, navigation, and relations for the new entities
  • register secret provider/secret nodes and templates on the server

Testing

  • pnpm proto:generate
  • pnpm -r run lint
  • pnpm --filter @agyn/platform-ui run typecheck
  • pnpm --filter @agyn/platform-server run typecheck
  • pnpm --filter @agyn/platform-ui test

Tests: 448 passed (85 files). Lint: no errors.

@rowan-stein
Copy link
Contributor

Implementation complete for #1393. All local checks pass:

  • ✅ Lint clean
  • ✅ Typecheck (UI + Server)
  • ✅ 448 UI tests passing

Requesting review.

noa-lucent
noa-lucent previously approved these changes Mar 13, 2026
Copy link
Contributor

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean, well-structured PR that correctly adds Secret Provider and Secret entity kinds across server and UI. The changes follow existing patterns consistently, route paths avoid collision with the existing Vault-based secrets feature, and no existing secrets code was touched.

Two minor comments on using the templateViewFor()/templateViewComponent() fallback pattern for consistency with all other entity kinds in the config view switches. Not blocking — no template overrides exist today for these kinds — but worth aligning.

Nicely done.

@casey-brooks
Copy link
Contributor Author

Summary

  • removed graph/node/template integration for secret providers and entity secrets across server/UI
  • added gateway API modules plus React Query hooks for secret providers and secrets (CRUD + resolve)
  • rebuilt Secret Providers and Secrets list pages with gateway CRUD dialogs, filters, and pagination

Lint

  • pnpm --filter @agyn/platform-ui lint (no errors)
  • pnpm --filter @agyn/platform-server lint (no errors)

Typecheck

  • pnpm --filter @agyn/platform-ui typecheck
  • pnpm --filter @agyn/platform-server typecheck

Tests

  • pnpm --filter @agyn/platform-ui test (85 files, 448 passed, 0 failed, 0 skipped)

@rowan-stein
Copy link
Contributor

Rework Complete — Ready for Review

This PR has been reworked to use gateway-backed CRUD instead of graph/node integration.

What changed:

  • Removed all server-side nodes, template registrations, and graph entity type changes
  • Added gateway REST API modules (/apiv2/secrets/v1/...) for Secret Providers and Secrets
  • Added React Query hooks following the Variables pattern
  • Rebuilt list pages with CRUD dialogs, filtering, pagination, and resolve flow
  • Existing vault-based secrets code (features/secrets/, components/secrets/, SettingsSecrets.tsx) is untouched

CI: All 7 checks passing ✅

Lint | Test Server | Test UI | Storybook Smoke | LiteLLM Integration | Build Server | Build UI

Requesting review.

Copy link
Contributor

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the rework — the graph/node approach is fully removed and the gateway-backed CRUD pattern is the right direction. The API modules have proper boundary parsing, hooks follow the Variables pattern, types match the issue spec, and the routing/nav additions are correct.

However, there are several structural issues that need addressing before merge:

Major:

  1. Duplicated code across new filesextractErrorCode (3 copies), boundary parsing helpers (isRecord, readString, etc. — 2 copies), computePaginationWindow + formatTimestamp + pagination constants (2 copies each). These should be extracted into shared utilities.
  2. Monolithic page components (524 + 640 lines) — the page components each handle pagination, form state, validation, submit, delete confirmation, and table rendering. Extract reusable pieces: form hooks, <PaginationBar>, <ActionIconButton> (tooltip-wrapped icon button used 5× across both pages).
  3. No hook tests — the reference pattern (variables/hooks.ts) has a full test suite, but no tests were added for the new hooks.

Minor:
4. Magic perPage: 100 for provider dropdown in EntitySecretsListPage.

Previous review threads from the graph/node version have been resolved as those files are no longer in scope.

@casey-brooks
Copy link
Contributor Author

Summary

  • Extracted shared parsing, error, pagination, and timestamp helpers for secrets/providers.
  • Decomposed secrets/provider list pages into hooks/components with shared action/pagination UI.
  • Added entity secrets/provider hook coverage mirroring variables tests.

Testing

  • pnpm --filter @agyn/platform-ui lint (no issues)
  • pnpm --filter @agyn/platform-ui typecheck (no issues)
  • pnpm --filter @agyn/platform-ui test (Tests: 459 passed, 0 failed, 0 skipped)

noa-lucent
noa-lucent previously approved these changes Mar 13, 2026
Copy link
Contributor

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 6 prior review comments verified as resolved in code:

  1. extractErrorCode extraction ✓ — Shared in @/lib/extractErrorCode.ts, imported by all 3 hook files (including refactored variables/hooks.ts).
  2. Parsing helpers extraction ✓ — Shared in @/api/parsing.ts, imported by both API modules. No local copies remain.
  3. Pagination/timestamp extraction ✓ — @/lib/pagination.ts (with getPaginationMeta, computePaginationWindow, and named constants) and @/lib/formatTimestamp.ts. Both pages import from shared.
  4. Page decomposition ✓ — Both pages decomposed into focused subcomponents (Header, Table, FormDialog, DeleteDialog, ResolveDialog) and custom form hooks (useProviderForm, useSecretForm). Shared <ActionIconButton> and <PaginationBar> components extracted. Orchestrator functions are clean and readable.
  5. Hook tests ✓ — 11 new test cases covering query success/error, mutation success notifications + cache invalidation, error notifications via extractErrorCode, and resolve error path.
  6. Magic number ✓ — PROVIDER_DROPDOWN_PAGE_SIZE named constant replaces the inline 100.

Clean, well-structured refactor. Good to merge.

@casey-brooks
Copy link
Contributor Author

Summary

  • switch secret provider/secret API parsing and hooks to token-based pagination
  • update secret provider/secret list pages and PaginationBar for cursor-driven load more
  • refresh entity secrets hook tests for nextPageToken pagination

Testing

  • pnpm --filter @agyn/platform-ui lint (no errors)
  • pnpm --filter @agyn/platform-ui typecheck
  • pnpm --filter @agyn/platform-ui test (passed: 461, failed: 0, skipped: 0)

noa-lucent
noa-lucent previously approved these changes Mar 13, 2026
Copy link
Contributor

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean migration from offset-based to token-based pagination. All changes verified:

  • API modules: page/perPage/total replaced with pageSize/pageToken/nextPageToken. readNumber import correctly removed. Boundary parsing updated.
  • Hooks: useQueryuseInfiniteQuery with fully typed generic parameters, proper initialPageParam, and getNextPageParam using normalizePageToken.
  • Pages: Offset state (page, safePage, getPaginationMeta) replaced with flatMap over data.pages and fetchNextPage/hasNextPage/isFetchingNextPage. The useEffect for page clamping correctly removed.
  • PaginationBar: Simplified to "Load more" pattern matching token-based pagination semantics.
  • pagination.ts: Offset utilities removed, normalizePageToken added. DEFAULT_PAGE_SIZE retained.
  • Tests: 2 new multi-page token pagination tests (providers + secrets) with fetchNextPage and toHaveBeenNthCalledWith assertions verifying correct token forwarding.

One nit on dead readNumber export. Good to merge.

@casey-brooks
Copy link
Contributor Author

Summary

  • added full-page secret provider and entity secret upsert pages with edit loading/validation
  • updated secret provider and secret list pages to navigate to new/edit routes and removed dialog-based forms
  • wired new routes in App.tsx and added shared provider label helper

Testing

  • pnpm --filter @agyn/platform-ui lint
  • pnpm --filter @agyn/platform-ui typecheck
  • pnpm --filter @agyn/platform-ui test (86 files, 461 passed)

Lint

  • no errors

noa-lucent
noa-lucent previously approved these changes Mar 13, 2026
Copy link
Contributor

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean migration from dialog-based forms to dedicated upsert pages. All changes verified:

  • New SecretProviderUpsertPage and EntitySecretUpsertPage follow the existing EntityUpsertPage pattern: props-driven mode, useParams for entity ID, useNavigate for cancel/success, loading overlay, not-found alert, and inline submit error.
  • Routes follow the established /:entity/new and /:entity/:entityId/edit convention.
  • List pages properly simplified: dialog components, form hooks, and create/update mutation hooks removed. Navigation handlers delegate to the new routes. Delete uses window.confirm, consistent with EntityListPage.
  • Shared utils extracted to features/entitySecrets/utils.ts (buildProviderLabel, PROVIDER_DROPDOWN_PAGE_SIZE), shared by both the upsert page and list page.
  • ResolveSecretDialog correctly converted to inline ResolveSecretPanel (no dialog needed since it's read-only).
  • Provider filter preserved via ?providerId= query param when navigating to create secret — picked up by useSearchParams in the upsert page.
  • Provider options fallback in edit mode correctly handles the case where the selected provider isn't in the loaded dropdown page.

One minor: dead createDisabled prop chain in SecretProvidersListPage. Not blocking.

@casey-brooks
Copy link
Contributor Author

Summary:

  • restored relation dropdown prefill handling and placeholder clearing in EntityUpsertForm alongside updated dropdown-driven tests.
  • replaced remaining SelectInput usage in secret provider/secret pages with Dropdown, including updated provider filtering and list-page template picker assertions.

Tests:

  • pnpm --filter @agyn/platform-ui lint
  • pnpm --filter @agyn/platform-ui typecheck
  • pnpm --filter @agyn/platform-ui test (471 passed)

noa-lucent
noa-lucent previously approved these changes Mar 14, 2026
Copy link
Contributor

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean SelectInputDropdown (Radix Select) migration. All changes verified:

  • 3 page components (SecretProviderUpsertPage, EntitySecretUpsertPage, EntitySecretsListPage) and EntityUpsertForm correctly migrated from onChange event handlers to onValueChange direct-value API.
  • Radix deselection workaround: Sentinel constants (ALL_PROVIDERS_VALUE, EMPTY_RELATION_VALUE) correctly handle Radix Select's no-deselect constraint — applied where deselection is needed (filter dropdown, relation dropdowns), correctly omitted where selection is required (provider field in secret upsert).
  • Test updates: Thorough — pointer capture polyfills for jsdom, pointerEventsCheck: 0 on userEvent.setup(), findByLabelText for single-relation selects, data-state="checked" assertions, removed within(listbox) scoping (Radix portals). All CI green.
  • No leftover SelectInput references in the codebase.

Previous minor (createDisabled = false in SecretProvidersListPage) resolved as non-blocking.

@casey-brooks
Copy link
Contributor Author

Summary:

  • set size=\"sm\" on secret provider/secret upsert Inputs and Dropdowns to align heights.

Tests:

  • pnpm --filter @agyn/platform-ui lint
  • pnpm --filter @agyn/platform-ui typecheck
  • pnpm --filter @agyn/platform-ui test (471 passed)

Copy link
Contributor

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Straightforward styling pass — size="sm" added to all Input and Dropdown fields on both upsert pages for consistent compact heights. Textarea correctly left at default since its height is row-driven. Both components accept size: 'sm' | 'default' in their type definitions. No logic changes, CI green. LGTM.

@rowan-stein rowan-stein added this pull request to the merge queue Mar 14, 2026
Merged via the queue into main with commit b4f6d48 Mar 14, 2026
13 of 14 checks passed
casey-brooks added a commit that referenced this pull request Mar 14, 2026
* feat(entities): add secret provider kinds

* refactor(secrets): move to gateway CRUD

* refactor(ui): extract secrets helpers

* fix(secrets): use token pagination

* feat(ui): add secret upsert pages

* fix(ui): stabilize dropdown selections

* fix(ui): align secret form sizes
github-merge-queue bot pushed a commit that referenced this pull request Mar 14, 2026
* refactor(platform): drop docker-runner

* feat: add secret provider entities (#1394)

* feat(entities): add secret provider kinds

* refactor(secrets): move to gateway CRUD

* refactor(ui): extract secrets helpers

* fix(secrets): use token pagination

* feat(ui): add secret upsert pages

* fix(ui): stabilize dropdown selections

* fix(ui): align secret form sizes

* test: centralize docker client stubs
casey-brooks added a commit that referenced this pull request Mar 15, 2026
* refactor(platform): drop docker-runner

* feat: add secret provider entities (#1394)

* feat(entities): add secret provider kinds

* refactor(secrets): move to gateway CRUD

* refactor(ui): extract secrets helpers

* fix(secrets): use token pagination

* feat(ui): add secret upsert pages

* fix(ui): stabilize dropdown selections

* fix(ui): align secret form sizes

* test: centralize docker client stubs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Secret Providers and Secrets entity pages to Platform UI

4 participants