Skip to content

feat(config): config-as-code (get, set, roles, diff, apply)#56

Merged
Bccorb merged 1 commit into
mainfrom
feat/config-command
Jul 14, 2026
Merged

feat(config): config-as-code (get, set, roles, diff, apply)#56
Bccorb merged 1 commit into
mainfrom
feat/config-command

Conversation

@Bccorb

@Bccorb Bccorb commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Seventh issue in the CLI auth epic (#38), the flagship authenticated capability. Adds seamless config to read and write an instance's system configuration from the terminal, turning the dashboard's config panel into something versionable, diffable, and CI-applicable.

Commands

  • seamless config get [key] [--json]: GET /system-config/admin. Prints the whole config or one key. --json emits raw JSON (pipe to a file).
  • seamless config set <key> <value>: PATCH /system-config/admin. The value is parsed as JSON with a string fallback, so all shapes work: config set access_token_ttl 15m, config set rate_limit 250, config set passkey_login_fallback_enabled false, config set login_methods '["email_otp","passkey"]'.
  • seamless config roles [--json]: GET /system-config/roles.
  • seamless config diff <file>: shows how a local JSON config file differs from the instance (per-key from/to).
  • seamless config apply <file> [--dry-run]: applies the delta after a confirmation prompt; --dry-run previews without applying.

Notes / decisions

  • Endpoint path: the issue says GET/PATCH /system-config, but the actual admin endpoints are /system-config/admin (both under requireAdmin); /system-config/roles is separate. Used the real paths.
  • Writable keys: apply filters a file down to the patch-schema's writable keys (app_name, default_roles, available_roles, login_methods, passkey_login_fallback_enabled, oauth_providers, lockout_policy, access_token_ttl, refresh_token_ttl, rate_limit, delay_after, rpid, origins) and reports the rest as ignored. This means a full config captured with config get --json > config.json can be edited and applied without tripping the server's .strict() patch schema (which would 400 on read-only keys like frontend_url).
  • Apply sends only the delta: apply diffs the file against the instance and PATCHes just the changed keys.
  • "Invalidate cached read": the CLI holds no local cache of system config; every command fetches fresh, so this is inherently satisfied.
  • Permissions: a 403 becomes a clear "requires an admin role" message; 400 validation details from the server are surfaced.

Structure

  • src/core/systemConfig.ts: getSystemConfig, patchSystemConfig, getRoles, parseValue, filterWritable, deepEqual, diffConfig, plus PermissionError / ConfigApiError.
  • src/commands/config.ts: the front end (rendering, file IO, confirmation).

Tests / verification

  • npm run build (tsc strict): passing.
  • npm test (vitest): 69 passing (11 new): admin get/patch/roles routing and payloads, 403 to PermissionError, 400 detail surfacing, parseValue across types, filterWritable dropping read-only keys, and deepEqual / diffConfig (changed and added keys).
  • Smoke-tested the front end: unknown subcommand, not-logged-in, and pre-auth handling.

Now that the Node 24 Dockerfile fix (#50) is merged, the conformance stack can start the auth-api again, so a live round-trip (get to a file, edit, diff, apply) can be added as a CLI conformance spec under #47.

Acceptance criteria

  • Round-trip works: get to a file, edit, diff, then apply reflects on the instance (covered by unit tests for each step; live spec to follow in CLI auth docs and conformance tests #47).
  • Token TTLs, origins, login methods, and WebAuthn RP settings are all readable and writable (all in the writable-key set).
  • A non-privileged user receives a clear permission error.

Closes #45

Add seamless config to read and write an instance's system configuration from
the terminal. config get [key] reads GET /system-config/admin (with --json),
config set <key> <value> writes one key via PATCH /system-config/admin (the
value is parsed as JSON with a string fallback, so token TTLs, origins, login
methods, and WebAuthn RP settings are all writable), and config roles lists the
instance roles from GET /system-config/roles.

config diff <file> shows how a local JSON config file differs from the instance,
and config apply <file> applies the delta after a confirmation prompt, with
--dry-run to preview. Apply filters a file down to the writable keys, so a full
config captured with config get can be applied without tripping the strict patch
schema. A non-admin user receives a clear permission error, and 400 validation
details are surfaced. The network and diff logic lives in core/systemConfig.ts
and is unit tested against an injected client; commands/config.ts is the front
end. Accepts --profile and honors SEAMLESS_PROFILE.

Closes #45
@Bccorb
Bccorb merged commit 0507684 into main Jul 14, 2026
1 check failed
@Bccorb
Bccorb deleted the feat/config-command branch July 14, 2026 02:48
Bccorb added a commit that referenced this pull request Jul 17, 2026
feat(config): config-as-code (get, set, roles, diff, apply)
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.

seamless config command (config-as-code)

1 participant