Skip to content

feat: CCP-5602 api key generation - #210

Merged
barrfalk merged 21 commits into
mainfrom
CCP-5602-API-Key-Generation
Sep 11, 2026
Merged

barrfalk merged 21 commits into
mainfrom
CCP-5602-API-Key-Generation

Conversation

@barrfalk

@barrfalk barrfalk commented Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator

Tenants can now generate their own API key from the Notify Settings screen. Onboarding drops from three manual steps (request a key in the API Services Portal → create a CSTAR tenant → bind the key via Postman) to two: create the CSTAR tenant, then click Generate in Notify, which mints the credential and binds it to the tenant in one call.

Why it isn't enabled everywhere

Issuing a key calls the APS Credential Issuer API, which is deployed only on the APS test instance. The production instance returns 404 for it. So the environments split:

API gateway Key issuing api_key_self_service flag
PR / DEV / TEST APS test instance (notify-test) from the Notify UI ON
PROD APS production instance (gw-fe8c5) not available OFF

Production behaviour is unchanged. Tenants there still request a key in the Portal and bind it with POST /api/v1/service/api-key/bind, and tenant resolution still works off the Kong credential identifier exactly as before. The two onboarding paths are mutually exclusive on the same flag, so an environment never offers both: where the UI issues keys, the bind route returns 404.

The flag is seeded OFF (V59), so merging this cannot expose a surface that would fail. Enable it per environment from the Feature Flags admin screen.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update
  • Documentation update

How Has This Been Tested?

  • New unit tests
  • New integrated tests
  • New component tests
  • New end-to-end tests
  • New user flow tests
  • No new tests are required
  • Manual tests (description below)
  • Updated existing tests

Checklist

  • I have read the CONTRIBUTING doc
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have already been accepted and merged

Further comments


Thanks for the PR!

Deployments, as required, will be available below:

Please create PRs in draft mode. Mark as ready to enable:

After merge, new images are deployed in:

Implement end-to-end tenant API key self-service: add APS Credential Issuer integration, new frontend JWT-protected API key endpoints (list/issue/regenerate/update notes), and a DB migration to support client IDs, notes, issuance metadata, and nullable credential identifiers. Update tenant resolution guards to handle both credential identifiers and client IDs with backfill, and restrict the legacy bind endpoint to load-test-only autobind behavior. Add the Settings UI for generating/revealing/regenerating keys with note capture, plus supporting API/thunks/slice/types and tests, and align page/layout components and tooltip behavior with shared UI patterns.
Adds end-to-end safeguards around API key self-service issuance. The backend now enforces one self-service key per tenant with a partial unique index (V55), generates unique APS application names, uses CSTAR tenant labels, and converts race-condition unique violations into a clear conflict while logging orphaned consumers for manual cleanup. It also tightens notes update validation by requiring the `notes` field (nullable to clear).

Guard resolution now only accepts `clientId` fallback for never-activated bindings (`credentialIdentifier IS NULL`). Frontend API key UX keeps the reveal modal open when note saving fails (to avoid losing typed notes), conditionally hides unset help links, and updates default docs/revoke link behavior. Devcontainer APS product mock now enforces gateway scoping to match real API permissions.
@barrfalk
barrfalk marked this pull request as draft August 27, 2026 15:46
@barrfalk barrfalk closed this Sep 2, 2026
@barrfalk barrfalk reopened this Sep 2, 2026
Adds the `api_key_self_service` feature flag and uses it to gate the Settings UI and frontend API key issuance routes. Also updates key binding flow, labels issued credentials by release, and keeps the manual bind/load-test paths working for environments that cannot issue keys from the UI.
@barrfalk
barrfalk marked this pull request as ready for review September 9, 2026 21:30
barrfalk and others added 3 commits September 10, 2026 15:17
API keys issued through the APS Credential Issuer only authenticate against a
gateway on the APS test instance, so DEV, TEST and PR routes now publish to
notify-test there. The layout mirrors gw-fe8c5: a dev qualifier holding DEV
plus each open PR at /pr-<n>, and a test qualifier holding TEST. PROD stays on
gw-fe8c5 and its generated config is byte-identical.

- config/test-instance/: dev, test and pr stage files, the Product, and the
  cutover steps
- generate-gateway-config.sh: GATEWAY_INSTANCE=test selects those stages
- publish-test-instance.sh: shared publish with rejection and secret checks
- pr-open, pr-close, merge: publish to notify-test with
  GWA_ACCT_TEST_INSTANCE; PR frontends proxy to the test-instance dev host
- pr-close: republish DEV with the remaining PRs. Publishing the remaining
  PRs alone deleted DEV's routes from the dev qualifier.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gwa publish-gateway ignores --gateway and reads the gateway from
~/.gwa-config.yaml, so the first CI publish to notify-test failed with
"No gateway has been set" after logging in successfully. Set it with
`gwa config set gateway` and drop the ignored flag.

The test-instance README now notes both gwa quirks: the gateway has to be in
config, and input paths resolve against the working directory even when
absolute. Its cleanup example is corrected to match.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NotificationController is a published, non-frontend API, but it was guarded by
NotifyFrontendRoleGuard, which requires a Keycloak user JWT. Kong routes it
with key-auth, so no single credential got through: the backend rejected a key
and the gateway rejected a JWT. The Notify UI reads this data from
NotificationFrontendController.

- Guard with NotifyServiceGuard; drop @ApiBearerAuth, the NOTIFY_ADMIN role
  checks and their 403 docs
- Import ApiKeysModule for the guard's ApiKeyConsumer repository
- Unit spec asserts the controller's guard; the backend e2e spec now expects a
  JWT to be rejected

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Icon updates
Menu text updates
Fixed bug with API Limits where the count on the UI was not accurate.
@barrfalk
barrfalk merged commit 3eed6c2 into main Sep 11, 2026
19 of 20 checks passed
@barrfalk
barrfalk deleted the CCP-5602-API-Key-Generation branch September 11, 2026 17:15
NikhilMM89 added a commit that referenced this pull request Oct 2, 2026
…oints at (CCP-5824)

diff_branch defaulted to main, so a push to main diffed main against main —
always empty, so the build never triggered and the action retagged :latest
onto :dev instead. :latest is whichever image was tagged most recently by any
build, so the deployed image depended on timing. After #229 merged, DEV and
TEST ran the #210 frontend and the run still went green.

- merge.yml: diff_branch HEAD^ so only packages the merge touched rebuild,
  from the merge commit; tag_fallback dev so an untouched package keeps the
  image it had
- pr-open.yml: same tag_fallback change — unchanged packages in a PR env were
  also being filled from :latest
- Log per package whether the image was built or retagged, plus the digest

Verified the HEAD^ diff against the last five merge commits: #245 frontend
only, #242 backend+frontend, #244 all three.
barrfalk pushed a commit that referenced this pull request Oct 6, 2026
…oints at (CCP-5824) (#254)

* fix(ci): deploy the merged commit's own image, not whatever :latest points at (CCP-5824)

diff_branch defaulted to main, so a push to main diffed main against main —
always empty, so the build never triggered and the action retagged :latest
onto :dev instead. :latest is whichever image was tagged most recently by any
build, so the deployed image depended on timing. After #229 merged, DEV and
TEST ran the #210 frontend and the run still went green.

- merge.yml: diff_branch HEAD^ so only packages the merge touched rebuild,
  from the merge commit; tag_fallback dev so an untouched package keeps the
  image it had
- pr-open.yml: same tag_fallback change — unchanged packages in a PR env were
  also being filled from :latest
- Log per package whether the image was built or retagged, plus the digest

Verified the HEAD^ diff against the last five merge commits: #245 frontend
only, #242 backend+frontend, #244 all three.

* fix(charts): raise the promtail sidecar memory limit from 128Mi to 256Mi

ContainerMemoryHigh fired on two prod frontend pods. The frontend container
itself is nowhere near its limit (39-57Mi against 8Gi); it is the promtail
sidecar enabled alongside it, sitting at 109Mi of a 128Mi limit - 85.2%, which
is exactly the alert threshold.

It is not log volume. access.log is 664KB after four days and promtail's
positions file shows it fully consumed, so there is no backlog. 60-110Mi is
simply promtail's resting Go footprint, and the chart's 128Mi left no headroom.
Test shows the same spread, 55Mi and 103Mi.

Nothing has OOMKilled yet. The reason to fix it ahead of that: the app container
has its own limit, so an OOMKilled promtail costs no user-visible service - it
just stops frontend logs reaching Loki and quietly blinds the frontend log
alerts again.

Requests go to 128Mi and limits to 256Mi, roughly 2.5x the observed peak.
Costs 320Mi of requests across five prod replicas, against 7.4Gi of headroom.
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.

2 participants