Skip to content

Consolidate ai-workspace / developer-portal setup scripts and fix compose profile gating - #2892

Merged
Krishanx92 merged 12 commits into
wso2:mainfrom
Thushani-Jayasekera:fix-configs
Jul 28, 2026
Merged

Consolidate ai-workspace / developer-portal setup scripts and fix compose profile gating#2892
Krishanx92 merged 12 commits into
wso2:mainfrom
Thushani-Jayasekera:fix-configs

Conversation

@Thushani-Jayasekera

@Thushani-Jayasekera Thushani-Jayasekera commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

portals/ai-workspace/setup.sh and portals/developer-portal/scripts/setup.sh were two near-duplicate copies of the same provisioning logic that had drifted apart. This PR replaces both with a single shared script (portals/scripts/setup.sh), fixes the docker-compose profiles config in both packs so that platform-api — previously always-on with no profile — is now correctly gated like every other service, and has setup.sh write a default COMPOSE_PROFILES into .env so a plain docker compose up -d (no --profile flag) still starts the right services for whichever pack you're in. It also moves every secret that can be file-mounted — including the Developer Portal's at-rest encryption key and session secret, previously env vars — off of api-platform.env and onto resources/keys/* files read via {{ file }}.

Changes

1. Single shared setup.sh (portals/scripts/setup.sh)

  • Deletes portals/ai-workspace/setup.sh and portals/developer-portal/scripts/setup.sh; one script now serves both quickstarts and their distribution zips.
  • Self-locates its working directory (checks $PWD, then next to the script, then its parent) so the same file works whether invoked as ../scripts/setup.sh from a dev checkout or ./scripts/setup.sh from a distribution zip.
  • Behavior is otherwise unchanged: idempotent by default (fills in only what's missing), --force rotates the TLS cert / JWT keypair / admin credentials, --certs-only generates just the TLS cert (used by make bff-run). (--force's scope was narrowed during review — see item 6.)
  • make dist in both ai-workspace/Makefile and developer-portal/Makefile now copies this shared script into the distribution scripts/ directory instead of each pack's own copy, and bakes in two pack-specific values via sed (see item 3).

2. docker-compose.yaml — fixed profile gating (both packs)

  • platform-api previously had no profiles entry, so it always started regardless of which --profile flag was passed — it wasn't actually optional/gated, it just always ran alongside whatever else was selected. It's now explicitly listed under every profile that needs it: ["platform-api", "ai-workspace", "all"] (ai-workspace pack) and ["platform-api", "developer-portal", "all"] (developer-portal pack) — making --profile platform-api a real "platform-api only" mode.
  • The sibling optional service's profile name changed from with-developer-portal / with-ai-workspace to plain developer-portal / ai-workspace, and both now also participate in a new all profile alongside their own compose file's default service.
  • Added an in-file comment + example for running a service standalone against an externally-running platform-api via --no-deps (skips the depends_on: service_healthy wait — documented as a prerequisite the caller must satisfy themselves).

3. COMPOSE_PROFILES default via .env — a plain docker compose up -d works again

  • Gating platform-api behind a profile (item 2) meant a bare docker compose up -d with no flags would start nothing. Fixed by having setup.sh write COMPOSE_PROFILES=<pack's default profiles> into a project-level .env file (which Compose reads automatically, unlike api-platform.env which is only ever passed to containers explicitly via each service's env_file:) — so a plain docker compose up -d after running setup.sh once again starts the right services, and an explicit --profile flag is only needed to add an optional component or override the default.
  • Resolution order: an explicit --profiles=<a,b,...> flag to setup.sh always wins; otherwise a value make dist bakes into DEFAULT_COMPOSE_PROFILES for a shipped distribution zip; otherwise the script auto-detects the pack from docker-compose.yaml's own service topology (see below) and picks that pack's usual two-service default.
  • Pack detection (used both for the COMPOSE_PROFILES default and for the printed "next step" hint) no longer greps for a comment's exact wording, which would silently break if the comment were ever reworded. It now checks the compose file's actual service topology — each pack's mandatory service has a structurally distinct name (devportal: vs developer-portal:) — and make dist also bakes a DEFAULT_PACK_NAME the same way it bakes DEFAULT_COMPOSE_PROFILES, so a shipped distribution zip never needs to detect anything at runtime at all.
  • Verified empirically (not just assumed) that Compose's --profile CLI flag does not merge with COMPOSE_PROFILES from .env — passing --profile ai-workspace alone, with COMPOSE_PROFILES=ai-workspace,platform-api already set, activates only ai-workspace. It's safe as an "add an optional service" pattern anyway, because Compose only reconciles containers within the profile(s) you name on that invocation — already-running containers from an earlier default up -d are left alone, not stopped.

4. Command surface — before / after

Before this PR After (current state)
ai-workspace pack, primary docker compose up -d docker compose up -d (after setup.sh has run — reads the default from .env) or docker compose --profile ai-workspace --profile platform-api up -d (explicit, works with no .env default at all)
+ developer portal docker compose --profile with-developer-portal up -d docker compose --profile developer-portal up -d (adds to the already-running default) or docker compose --profile ai-workspace --profile developer-portal --profile platform-api up -d (explicit, full set in one invocation)
developer-portal pack, primary docker compose up -d docker compose up -d (after setup.sh has run — reads the default from .env) or docker compose --profile developer-portal --profile platform-api up -d (explicit, works with no .env default at all)
+ AI Workspace docker compose --profile with-ai-workspace up -d docker compose --profile ai-workspace up -d (adds to the already-running default) or docker compose --profile developer-portal --profile ai-workspace --profile platform-api up -d (explicit, full set in one invocation)
everything (not available as one profile) docker compose --profile all up -d
platform-api only (not actually isolated — always ran) docker compose --profile platform-api up -d
ai-workspace only, against an externally-running platform-api (not available) docker compose up -d --no-deps ai-workspace (after setup.sh) or docker compose --profile ai-workspace up -d --no-deps ai-workspace (explicit)
developer-portal only, against an externally-running platform-api (not available) docker compose up -d --no-deps devportal (after setup.sh) or docker compose --profile developer-portal up -d --no-deps devportal (explicit)

setup.sh's closing "next step" hint reflects whichever COMPOSE_PROFILES value was actually just written to .env (which can differ from the pack's usual default if --profiles=<...> or a dist-baked value was used), defaults-first, including --profile all and --profile platform-api.

image

5. At-rest encryption keys and session secrets — env vars → mounted files (both packs)

  • Platform API (picked up while resolving a merge conflict with main): the at-rest encryption key is no longer written as APIP_CP_ENCRYPTION_KEY in api-platform.env. It's generated to resources/keys/encryption.key (32-byte key, 64 hex chars) and read by config.toml via {{ file "/etc/platform-api/keys/encryption.key" }} — the same resources/keys mount already used for the JWT keypair.
  • Developer Portal (this round): APIP_DP_SECURITY_ENCRYPTION_KEY and APIP_DP_SECURITY_SESSION_SECRET are gone from api-platform.env too. Devportal's config.toml already supports {{ file }} interpolation with an allowlist covering /etc/devportal, and both compose files already mount resources/keys/jwt_public.pem into the container at /etc/devportal/keys/ — so the fix was to generate two more files there (resources/keys/devportal-encryption.key, devportal-session-secret), mount them alongside the JWT public key, and switch config.toml to {{ file "/etc/devportal/keys/encryption.key" }} / {{ file ".../session-secret" }}. api-platform.env now holds only APIP_CP_ADMIN_USERNAME / APIP_CP_ADMIN_PASSWORD_HASH.
  • Devportal's encryption key encrypts subscription/webhook secrets at rest (src/dao/subscriptionDao.js, webhookSubscriberDao.js) — the same risk profile as Platform API's own at-rest key — so it follows the identical rotation policy: preserved across --force, rotated only via --rotate-encryption-key. The session secret only signs session cookies (rotating it just invalidates sessions), so it follows --force like the TLS cert/JWT keypair. Both keys' rotation now share a single confirmation prompt instead of prompting twice.
  • Scoped deliberately to the docker-compose quickstart only — the same two env vars still appear as secretKeyRef-style env vars in the Kubernetes Helm chart (a standard, accepted k8s pattern) and in the IT/test compose configs and distribution/all-in-one, none of which were touched.

6. Docs and CI

  • README.md, QUICKSTART.md, and distribution/README.md in both packs updated for the new script path (../scripts/setup.sh) and, in this final round, to drop the now-redundant --profile <default> flag from every primary "bring the stack up" example in favor of a bare docker compose up (or up -d) — since setup.sh already wrote the right default into .env. The two genuinely-additive "turn on the optional sibling service" examples (docker compose --profile ai-workspace up -d from the devportal pack's docs and vice versa) were deliberately left alone, since they're correct as written (see item 3).
  • Two "restart after replacing the TLS cert" snippets (developer-portal/distribution/README.md, ai-workspace/distribution/README.md) also picked up --force-recreate, matching the one place that already had it correctly — a plain up -d won't recreate an already-running container just because a bind-mounted file changed underneath it.
  • .github/workflows/ai-workspace-pr-check.yml's "Start quickstart stack" step switched from docker compose --profile ai-workspace up -d --wait ... to a bare docker compose up -d --wait ..., since the setup.sh invocation earlier in the same job already writes COMPOSE_PROFILES to .env; the step's comment previously (and incorrectly, as of this PR) claimed --profile was required or Compose would select zero services.
  • ai-workspace/Makefile's bff-run and e2e-ci targets, and both Makefiles' dist targets, updated to call the shared script path.
  • IT compose comments (developer-portal/it/docker-compose.test*.yaml, it/Makefile) updated to reference the new script location (../../scripts/setup.sh); the IT stack's own cert/key generation (make ensure-certs) is unaffected — it doesn't use this script and still writes APIP_CP_ENCRYPTION_KEY as an env var for its own fixtures.
  • One known-stale doc not fixed in this PR: developer-portal/docs/introduction/quick-start.md describes an older layout (a ./scripts/setup.sh path that no longer exists, a configs/config-platform-api.toml that isn't generated by the current script) predating the shared-script design entirely. Flagged for a follow-up rather than folded into this diff.

7. Security hardening found in review

  • Least-privilege key mounts: both packs' docker-compose.yaml (and developer-portal/it/docker-compose.test.postgres.yaml) previously bind-mounted the entire resources/keys/.certs directory into the devportal/ai-workspace containers, which quietly also exposed jwt_private.pem and encryption.key to a service that only ever needs jwt_public.pem to verify tokens. Changed to mount just jwt_public.pem (matching the pattern the sqlite IT compose file already used) — and, this round, the two new devportal-specific secret files are mounted individually the same way, never the whole directory. Verified with docker compose config that platform-api still gets the full directory it actually needs.
  • File permissions: setup.sh previously wrote every generated secret (TLS private key, JWT private key, encryption key, api-platform.env) as 644 — world-readable to any other host user — with a comment calling it an accepted local-quickstart tradeoff. Now: 600 plus, where setfacl is available (Linux), an ACL entry granting read access specifically to the fixed non-root UID (10001) every service image runs as; falls back to the previous 644 when no working ACL mechanism exists (macOS's chmod +a can't target a numeric UID with no resolvable local account — tested directly, confirmed it fails silently, so the fallback path matters, not just theoretical). api-platform.env is 600 unconditionally since it's read by the Docker CLI/daemon, never bind-mounted into a container. The new devportal key/secret files go through the same restrict_secret_file helper.
  • --force no longer touches either at-rest encryption key: previously --force rotated everything including resources/keys/encryption.key, silently making any previously-encrypted data unreadable. Rotating it now requires a new, explicit --rotate-encryption-key flag, with an interactive type 'rotate' to confirm prompt (or the flag itself as confirmation in CI/non-interactive mode, i.e. when ADMIN_USERNAME/ADMIN_PASSWORD are set) — and, this round, the same flag and the same single confirmation prompt now also gate devportal's encryption key.
  • ai-workspace/Makefile's e2e-ci now also backs up/restores resources/keys and resources/certificates around its setup.sh --force call, not just docker-compose.yaml/api-platform.env — protects a local make e2e-ci run from clobbering keys/certs from a prior manual setup.sh run in the same checkout.
  • Admin credential consistency: setup.sh previously only checked APIP_CP_ADMIN_USERNAME for "already provisioned," so a partially-set env file (username present, hash missing — or vice versa) would either silently skip provisioning while broken, or pair a freshly generated username with a stale hash. Now checks both variables and fails with a specific recovery instruction if exactly one is present.

Behavior notes / things to verify

  • Not a compatibility break (fixed this round): an earlier version of this PR made a bare docker compose up -d start nothing, since platform-api became profile-gated with no default. That's resolved — after running setup.sh once, a bare docker compose up -d again starts the pack's usual two services, via .env's COMPOSE_PROFILES. Anyone who runs docker compose up -d without having run setup.sh first (e.g. copies an old .env-less checkout) still needs an explicit --profile.
  • Compatibility break: anyone with the old profile names (with-developer-portal, with-ai-workspace) in scripts/muscle memory needs to switch to the new flags (see table in item 4).
  • Compatibility break: anyone with an existing api-platform.env from before this change has stale APIP_CP_ENCRYPTION_KEY / APIP_DP_SECURITY_ENCRYPTION_KEY / APIP_DP_SECURITY_SESSION_SECRET lines that are no longer read; both services refuse to start until the corresponding resources/keys/* files exist (re-run setup.sh, which fills in only what's missing).
  • Compatibility break: anyone relying on --force to also rotate resources/keys/encryption.key or resources/keys/devportal-encryption.key now needs --rotate-encryption-key explicitly — --force alone leaves both untouched.
  • --profile all is symmetric between both packs' compose files (same three services), so --profile all behaves identically regardless of which pack's docker-compose.yaml you're driving it from.
  • setup.sh's pack-detection no longer depends on a comment's exact wording (see item 3) — verified the structural fallback (devportal: vs developer-portal: service keys) resolves correctly for both packs' checked-in compose files.

Test plan

  • docker compose --profile ai-workspace up -d from portals/ai-workspace — only platform-api + ai-workspace start
  • docker compose --profile developer-portal up -d from portals/developer-portal — only platform-api + developer-portal start
  • Empirically confirmed --profile <x> on the CLI does not merge with COMPOSE_PROFILES from .env, and that Compose leaves already-running out-of-scope containers alone on such an invocation
  • ../scripts/setup.sh then a bare docker compose up -d from each pack — starts platform-api + the pack's own service, no --profile needed
  • docker compose --profile all up -d from each pack — all three services start
  • docker compose --profile platform-api up -d — only platform-api starts
  • ../scripts/setup.sh run from both portals/ai-workspace and portals/developer-portal — correct pack-specific "next step" hint printed, resources/keys/encryption.key, devportal-encryption.key, and devportal-session-secret all generated
  • Re-run setup.sh without --force — existing encryption.key, devportal-encryption.key, and JWT keypair left untouched
  • setup.sh --force — TLS cert, JWT keypair, admin credentials, and devportal-session-secret rotate; both encryption keys do NOT
  • setup.sh --rotate-encryption-key — both encryption.key and devportal-encryption.key rotate, with a single shared confirmation prompt interactively
  • Devportal container starts successfully with only jwt_public.pem + the two new key files mounted (both packs' docker-compose.yaml, and it/docker-compose.test.postgres.yaml)
  • Devportal fails closed at startup if encryption.key or session-secret is missing/malformed (matches the existing 64-hex-char check, now sourced from a file instead of an env var)
  • make dist for both packs — distribution zip contains scripts/setup.sh with DEFAULT_COMPOSE_PROFILES and DEFAULT_PACK_NAME baked in, and runs correctly standalone
  • make bff-run (ai-workspace) and devportal IT suite still pass with updated script paths
  • ai-workspace-pr-check.yml's "Start quickstart stack" step succeeds with the bare docker compose up -d --wait command

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 68ed4802-7850-414d-802d-208eedf16da4

📥 Commits

Reviewing files that changed from the base of the PR and between 211cccb and f94c590.

📒 Files selected for processing (4)
  • .github/workflows/ai-workspace-pr-check.yml
  • portals/ai-workspace/docker-compose.yaml
  • portals/developer-portal/README.md
  • portals/developer-portal/docker-compose.yaml
🚧 Files skipped from review as they are similar to previous changes (3)
  • portals/developer-portal/docker-compose.yaml
  • portals/ai-workspace/docker-compose.yaml
  • portals/developer-portal/README.md

📝 Walkthrough

Walkthrough

The change centralizes portal provisioning in portals/scripts/setup.sh, adds Compose profile-based startup, mounts generated secrets as individual files, updates packaging and CI integration, and revises quick-start and distribution documentation.

Changes

Portal setup and profile migration

Layer / File(s) Summary
Shared provisioning script
portals/scripts/setup.sh
Adds CLI parsing, root detection, certificate and key generation, secret-file provisioning, admin credential handling, profile configuration, rotation controls, and startup output.
Compose profiles and file-based secrets
portals/ai-workspace/docker-compose.yaml, portals/developer-portal/docker-compose.yaml, portals/developer-portal/configs/*, portals/developer-portal/src/config/configLoader.js, portals/developer-portal/it/*
Adds named Compose profiles, mounts selected key files, and changes Developer Portal security configuration and diagnostics to use mounted secret files.
Build, CI, and test integration
portals/*/Makefile, .github/workflows/*, portals/ai-workspace/.gitignore, portals/developer-portal/it/*
Updates setup-script paths, preserves E2E resources, stages shared setup scripts with distribution defaults, and updates CI and fixture references.
Startup and distribution documentation
portals/ai-workspace/README.md, portals/ai-workspace/distribution/README.md, portals/developer-portal/README.md, portals/developer-portal/distribution/README.md, portals/developer-portal/docker-compose.platform-api.yaml
Documents shared setup paths, external Platform API startup, profile-based commands, file-based secrets, credential output, and forced recreation for TLS changes.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant Setup as portals/scripts/setup.sh
  participant Files as api-platform.env and resources/keys
  participant Compose as docker compose
  participant Portal as devportal
  Developer->>Setup: Run provisioning script
  Setup->>Files: Write credentials and generated key material
  Setup->>Compose: Configure Compose profiles
  Compose->>Portal: Mount selected secret files
  Portal->>Files: Load file-based security configuration
Loading

Possibly related PRs

Suggested reviewers: renuka-fernando, krishanx92, piumal1999, virajsalaka, lasanthas

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: consolidating setup scripts and adjusting compose profile gating.
Description check ✅ Passed The description is detailed and covers purpose, changes, testing, and security, with only a few template sections omitted.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@portals/ai-workspace/distribution/README.md`:
- Around line 72-74: Update the Quick Start startup command to use the
ai-workspace Compose profile, replacing plain docker compose up -d with docker
compose --profile ai-workspace up -d. Revise the nearby “by default” wording to
reflect that AI Workspace and the Platform API start through this profile, while
preserving the optional Developer Portal description.
- Line 92: Update the Developer Portal lifecycle instructions in the README to
provide an explicit command that stops or removes the running service, such as
the profile-scoped compose down or service stop command, instead of saying to
omit the profile on later commands.

In `@portals/ai-workspace/Makefile`:
- Line 122: Update the e2e-ci recipe around the setup.sh --force invocation to
preserve persistent resources: back up and restore resources/keys/encryption.key
and the generated TLS certificate files alongside the existing api-platform.env
and docker-compose.yaml backups, ensuring cleanup leaves all keys and
certificates unchanged.

In `@portals/developer-portal/distribution/README.md`:
- Line 94: Clarify the AI Workspace profile guidance in the README: explain that
later docker compose up commands without --profile ai-workspace neither start
nor reconcile AI Workspace, and that an already-running instance remains
running. Document the explicit cleanup options using docker compose stop
ai-workspace or docker compose --profile ai-workspace down.

In `@portals/developer-portal/README.md`:
- Line 252: Update the Docker Compose volume mounts for the Developer Portal and
optional AI workspace portal to expose only jwt_public.pem, not the entire
resources/keys directory; then revise the README statement to accurately
describe the public-key-only mount and ensure private keys and encryption.key
remain unavailable to portal containers.

In `@portals/scripts/setup.sh`:
- Around line 214-239: Update the existing-credentials check around
APIP_CP_ADMIN_USERNAME and APIP_CP_ADMIN_PASSWORD_HASH so provisioning is
skipped only when both variables are present. If exactly one is set, fail with a
clear recovery instruction or regenerate and write both credentials together;
never combine a newly generated username with an existing hash.
- Around line 107-110: Update the setup script’s FILE_MODE and generated-file
permission handling so private keys remain unreadable to other host users while
still accessible to the non-root container user via an appropriate owner/group
or ACL. Apply restrictive permissions to api-platform.env as well, and ensure
generated initial credentials are persisted only as a restrictive hash.
- Around line 203-209: Update the encryption.key generation branch in the setup
script so the generic FORCE/--force path never overwrites an existing at-rest
key. Preserve the existing key by default, and gate any intentional key
replacement behind a separate explicit destructive rotation or migration option
that requires confirmation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 25c3a8df-37b0-466b-8317-fcc5a3fe69e5

📥 Commits

Reviewing files that changed from the base of the PR and between b36df2e and 822b85b.

📒 Files selected for processing (15)
  • portals/ai-workspace/Makefile
  • portals/ai-workspace/QUICKSTART.md
  • portals/ai-workspace/README.md
  • portals/ai-workspace/distribution/README.md
  • portals/ai-workspace/docker-compose.yaml
  • portals/ai-workspace/setup.sh
  • portals/developer-portal/Makefile
  • portals/developer-portal/README.md
  • portals/developer-portal/distribution/README.md
  • portals/developer-portal/docker-compose.yaml
  • portals/developer-portal/it/Makefile
  • portals/developer-portal/it/docker-compose.test.postgres.yaml
  • portals/developer-portal/it/docker-compose.test.yaml
  • portals/developer-portal/scripts/setup.sh
  • portals/scripts/setup.sh
💤 Files with no reviewable changes (2)
  • portals/ai-workspace/setup.sh
  • portals/developer-portal/scripts/setup.sh

Comment thread portals/ai-workspace/distribution/README.md Outdated
Comment thread portals/ai-workspace/distribution/README.md Outdated
Comment thread portals/ai-workspace/Makefile
Comment thread portals/developer-portal/distribution/README.md Outdated
Comment thread portals/developer-portal/README.md Outdated
Comment thread portals/scripts/setup.sh Outdated
Comment thread portals/scripts/setup.sh Outdated
Comment thread portals/scripts/setup.sh Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026
@Thushani-Jayasekera

Thushani-Jayasekera commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Generated platform-api.env

APIP_DP_SECURITY_ENCRYPTION_KEY=xxx
APIP_DP_SECURITY_SESSION_SECRET=xx
APIP_CP_ADMIN_USERNAME=admin
APIP_CP_ADMIN_PASSWORD_HASH=xx

@renuka-fernando Are we following the approach of storing encryption keys in files rather than environment variables? If so, should we remove the Devportal encryption key and security session secret from the environment variables and use file-mounted secrets instead?

cc: @Piumal1999

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
portals/ai-workspace/Makefile (1)

374-374: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Ignore generated key material in distributions.

The shared setup script generates resources/keys/encryption.key and resources/keys/jwt_private.pem, but the .gitignore generated immediately above only excludes resources/certificates/*. Add resources/keys/* before shipping the distribution.

Proposed ignore rule
 		'*.env' \
 		'resources/certificates/*' \
+		'resources/keys/*' \
 		> $(DIST_DIR)/.gitignore
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/ai-workspace/Makefile` at line 374, Add resources/keys/* to the
generated distribution .gitignore alongside the existing
resources/certificates/* rule, ensuring setup.sh-generated encryption.key and
jwt_private.pem files are excluded before shipping the distribution.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ai-workspace-pr-check.yml:
- Line 63: Update the setup command in the workflow step using the
portals/ai-workspace working directory to invoke the shared script via
../scripts/setup.sh instead of ./scripts/setup.sh, preserving the existing
environment variables and command behavior.

---

Outside diff comments:
In `@portals/ai-workspace/Makefile`:
- Line 374: Add resources/keys/* to the generated distribution .gitignore
alongside the existing resources/certificates/* rule, ensuring
setup.sh-generated encryption.key and jwt_private.pem files are excluded before
shipping the distribution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c37b58f6-a590-4060-ae79-8f7918249ffe

📥 Commits

Reviewing files that changed from the base of the PR and between 822b85b and 1231ca3.

📒 Files selected for processing (9)
  • .github/workflows/ai-workspace-pr-check.yml
  • portals/ai-workspace/Makefile
  • portals/ai-workspace/distribution/README.md
  • portals/ai-workspace/docker-compose.yaml
  • portals/developer-portal/README.md
  • portals/developer-portal/distribution/README.md
  • portals/developer-portal/docker-compose.yaml
  • portals/developer-portal/it/docker-compose.test.postgres.yaml
  • portals/scripts/setup.sh
🚧 Files skipped from review as they are similar to previous changes (4)
  • portals/developer-portal/distribution/README.md
  • portals/developer-portal/docker-compose.yaml
  • portals/developer-portal/README.md
  • portals/scripts/setup.sh

Comment thread .github/workflows/ai-workspace-pr-check.yml Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026
@renuka-fernando

Copy link
Copy Markdown
Contributor

Generated platform-api.env

APIP_DP_SECURITY_ENCRYPTION_KEY=xxx
APIP_DP_SECURITY_SESSION_SECRET=xx
APIP_CP_ADMIN_USERNAME=admin
APIP_CP_ADMIN_PASSWORD_HASH=xx

@renuka-fernando Are we following the approach of storing encryption keys in files rather than environment variables? If so, should we remove the Devportal encryption key and security session secret from the environment variables and use file-mounted secrets instead?

cc: @Piumal1999

Yes, let's follow the same pattern.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026
…d update documentation for AI Workspace and Developer Portal

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
portals/developer-portal/README.md (1)

252-252: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Correct the Developer Portal secret-mount documentation.

The new configuration reads /etc/devportal/keys/encryption.key and /etc/devportal/keys/session-secret, so saying that encryption.key is never mounted contradicts the file-based secret change. Clarify that the Platform API’s private key and encryption key remain unavailable, while the Developer Portal’s own encryption and session-secret files are mounted at these target paths; ensure the Compose mounts match.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/developer-portal/README.md` at line 252, Update the secret-mount
documentation in the Developer Portal README to distinguish Platform API secrets
from portal secrets: state that the Platform API’s jwt_private.pem and
encryption.key remain unavailable to the portal, while the portal mounts its own
encryption.key and session-secret at /etc/devportal/keys/encryption.key and
/etc/devportal/keys/session-secret. Verify the corresponding docker-compose.yaml
mounts use these target paths.
.github/workflows/ai-workspace-pr-check.yml (1)

63-63: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not ship hardcoded CI credentials.

This workflow provisions a functional admin/admin account in every run. Generate a per-run password and export the resulting credentials to Cypress instead.

As per coding guidelines, files matching **/*.{go,toml,yaml,yml,Dockerfile} must not ship functional default or hardcoded credentials.

Proposed fix
-        run: ADMIN_USERNAME=admin ADMIN_PASSWORD=admin ../scripts/setup.sh
+        run: |
+          ADMIN_USERNAME="ci-${GITHUB_RUN_ID}"
+          ADMIN_PASSWORD="$(openssl rand -hex 32)"
+          export ADMIN_USERNAME ADMIN_PASSWORD
+          echo "::add-mask::$ADMIN_PASSWORD"
+          {
+            printf 'ADMIN_USERNAME=%s\n' "$ADMIN_USERNAME"
+            printf 'ADMIN_PASSWORD=%s\n' "$ADMIN_PASSWORD"
+            printf 'CYPRESS_ADMIN_USER=%s\n' "$ADMIN_USERNAME"
+            printf 'CYPRESS_ADMIN_PASSWORD=%s\n' "$ADMIN_PASSWORD"
+          } >> "$GITHUB_ENV"
+          ../scripts/setup.sh
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ai-workspace-pr-check.yml at line 63, Update the workflow
step invoking setup.sh to generate a unique password for each run instead of
using the hardcoded admin/admin credentials, then export the generated username
and password through the environment or mechanism consumed by Cypress so its
tests authenticate with those per-run credentials.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@portals/developer-portal/configs/config.toml`:
- Around line 93-94: Update the config entries for encryption_key and
session_secret to use explicit environment-variable fallbacks for local startup,
or extend the start:local template allowlist to permit the generated
resources/keys host directory. Ensure requireHexSecret() receives the generated
host secrets without relying on unavailable /etc/devportal/keys bind mounts.

---

Outside diff comments:
In @.github/workflows/ai-workspace-pr-check.yml:
- Line 63: Update the workflow step invoking setup.sh to generate a unique
password for each run instead of using the hardcoded admin/admin credentials,
then export the generated username and password through the environment or
mechanism consumed by Cypress so its tests authenticate with those per-run
credentials.

In `@portals/developer-portal/README.md`:
- Line 252: Update the secret-mount documentation in the Developer Portal README
to distinguish Platform API secrets from portal secrets: state that the Platform
API’s jwt_private.pem and encryption.key remain unavailable to the portal, while
the portal mounts its own encryption.key and session-secret at
/etc/devportal/keys/encryption.key and /etc/devportal/keys/session-secret.
Verify the corresponding docker-compose.yaml mounts use these target paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c05f67b-9a76-4ae2-bf5a-a8994000655d

📥 Commits

Reviewing files that changed from the base of the PR and between fbe07b8 and 211cccb.

📒 Files selected for processing (14)
  • .github/workflows/ai-workspace-pr-check.yml
  • portals/ai-workspace/.gitignore
  • portals/ai-workspace/Makefile
  • portals/ai-workspace/README.md
  • portals/ai-workspace/distribution/README.md
  • portals/ai-workspace/docker-compose.yaml
  • portals/developer-portal/Makefile
  • portals/developer-portal/README.md
  • portals/developer-portal/configs/config-template.toml
  • portals/developer-portal/configs/config.toml
  • portals/developer-portal/distribution/README.md
  • portals/developer-portal/docker-compose.yaml
  • portals/developer-portal/src/config/configLoader.js
  • portals/scripts/setup.sh
🚧 Files skipped from review as they are similar to previous changes (5)
  • portals/ai-workspace/docker-compose.yaml
  • portals/developer-portal/Makefile
  • portals/ai-workspace/Makefile
  • portals/developer-portal/docker-compose.yaml
  • portals/scripts/setup.sh

Comment thread portals/developer-portal/configs/config.toml
…ntials and update Docker Compose documentation for clarity
@Thushani-Jayasekera

Copy link
Copy Markdown
Contributor Author

Generated platform-api.env

APIP_DP_SECURITY_ENCRYPTION_KEY=xxx
APIP_DP_SECURITY_SESSION_SECRET=xx
APIP_CP_ADMIN_USERNAME=admin
APIP_CP_ADMIN_PASSWORD_HASH=xx

@renuka-fernando Are we following the approach of storing encryption keys in files rather than environment variables? If so, should we remove the Devportal encryption key and security session secret from the environment variables and use file-mounted secrets instead?
cc: @Piumal1999

Yes, let's follow the same pattern.

this is fixed. @Piumal1999 pls review

@Thushani-Jayasekera

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Krishanx92
Krishanx92 merged commit ad014b4 into wso2:main Jul 28, 2026
10 checks passed
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.

3 participants