Skip to content

new-env.mjs: accept --portal-auth-* / --portal-authz-* flags with posture validation #43

Description

@ChrisKrawczyk

Problem

deploy/scripts/new-env.mjs accepts CLI flags for infra/edge/TLS knobs
(--subscription, --location, --edge-mode, --tls-source,
--acme-email, --foundry-enabled) but not for portal auth
(PORTAL_AUTH_* / PORTAL_AUTHZ_*). Operators must scaffold first,
then edit the rendered .env by hand.

This creates two real failure modes:

  1. No early validation. Invariants like PROVIDER=entra
    ENTRA_TENANT_ID and ENTRA_CLIENT_ID must both be set are not
    caught at scaffold time. Bad config surfaces at the
    portal-manifests step, often after several minutes of Bicep.

  2. Sentinel-vs-empty trap. Operator clears __PS_UNSET__ to an
    empty string to express "I don't want this key set" — but
    substitute-env.mjs rejects empty values for portal config keys,
    only the literal sentinel passes. The portal-manifests step fails
    with Unresolved overlay .env keys: PORTAL_AUTHZ_ADMIN_GROUPS, ....
    Hit this during chkentra2 validation of PR Portal authz: deny-by-default; -AssignmentRequired is advanced opt-in #37; documented in
    .github/skills/pilotswarm-new-env-deploy/SKILL.md Step 3a but
    first-class flag validation would prevent the trap entirely.

Proposal

Add to new-env.mjs INPUTS:

  • --portal-auth-provider (none|entra)
  • --portal-auth-entra-tenant-id
  • --portal-auth-entra-client-id
  • --portal-auth-allow-unauthenticated (true|false)
  • --portal-authz-default-role (none|user|admin)
  • --portal-auth-entra-admin-groups
  • --portal-auth-entra-user-groups
  • --portal-authz-admin-groups
  • --portal-authz-user-groups

Cross-validate at scaffold time:

  • provider=entratenant-id and client-id both required
  • default-role must be in {none, user, admin}
  • Empty flag value (e.g. --portal-authz-admin-groups=) auto-rewrites
    to __PS_UNSET__ in the rendered .env, eliminating the trap.

Scope

  • deploy/scripts/new-env.mjs — INPUTS additions + cross-validation
  • deploy/scripts/test/new-env.test.mjs (or equivalent) — flag
    surface + invariant tests
  • .github/skills/pilotswarm-new-env-deploy/SKILL.md — Step 2 table
    • recommend flag-driven scaffold over scaffold-then-edit
  • deploy/scripts/README.md — flag reference table

Acceptance

  • Fresh stamp can be scaffolded fully non-interactively with no
    post-scaffold .env editing required.
  • new-env mystamp --portal-auth-provider=entra without
    --portal-auth-entra-tenant-id fails fast with a clear error.
  • Empty-string portal auth flag values render as __PS_UNSET__ in
    the rendered .env.

Context

Filed after deploying PR #37 (feature/default-assignment-required-false)
to a fresh chkentra2 stamp. PR #37 validated successfully end-to-end
(admin sign-in works, appRoleAssignmentRequired=false,
deny-by-default engine), but the deploy hit the sentinel-vs-empty trap
because I (Copilot CLI) cleared sentinels to empty strings when
hand-editing the scaffolded .env. This issue is the structural fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions