feat(spec-011): Plan and implement Entra External ID social login federation via spec-kit#507
Conversation
…ocess) Co-authored-by: MikeWedderburn-Clarke <5323631+MikeWedderburn-Clarke@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/CommunityManagement-Sample-Spec-Kit/sessions/a74a174b-f118-4a62-a195-f1bf0d228813
|
@copilot Update this branch from main. Then use spec kit process to impement the proposed changes |
|
@copilot Use spec-kit to plan and implement this on a separate branch in a separate environment in Azure. |
…tructure, directory features)
Implements all 34 tasks across 6 phases for Spec 011-entra-external-id: Phase 1 - Setup (T001-T005): - Add ENTRA_TENANT_DOMAIN to Zod env schema (config.ts) - SQL migration 011-001: extend users table with social auth columns (provider, provider_oid, avatar_url, updated_at); make email nullable for Apple relay users; add UNIQUE constraint on provider_oid - SQL migration 011-002: create linked_accounts table with CASCADE DELETE - Add LinkedAccount, SocialUserProfile, SocialProvider, UserSocialFields, ProviderButtonConfig, SOCIAL_PROVIDERS to packages/shared/src/types/auth.ts - Re-export new auth types from packages/shared/src/index.ts Phase 2 - Foundational (T006-T008): - Integration tests for upsertSocialUser + getUserIdByOid (social-user.test.ts) - Create social-user.ts: upsertSocialUser (ON CONFLICT upsert) + getUserIdByOid (UNION query: users.provider_oid + linked_accounts.provider_oid) - Update auth config.ts: CIAM issuer URL, signIn/jwt/session callbacks with oid-based user provisioning Phase 3 - User Stories 1, 2, 6 (T009-T015): - Integration tests for callbackUrl validation (login-redirect.test.ts) - Create callback-url.ts: validateCallbackUrl with open-redirect prevention - Create /login/page.tsx: server component with validated callbackUrl - Create LoginButtons.tsx: client component with Google/Facebook/Apple buttons, loading/error states, role=alert for errors, 44px touch targets - Create auth-messages.ts: all i18n strings (zero raw literals in JSX) - Create middleware.ts: redirect unauthenticated page routes to /login Phase 4 - Facebook and Apple (T016-T021): - T016/T017 tests already in social-user.test.ts (null email + Apple oid) - Apple display name fallback in resolveDisplayName() - Accessibility: aria-label, role=alert, aria-live, aria-busy, 44px targets Phase 5 - Account Linking (T022-T027): - Integration tests for link/unlink operations (link-account.test.ts) - Create link-account.ts: linkAccount + unlinkAccount + listLinkedAccounts - Create POST /api/auth/link with Zod validation + CSRF token verification - Create GET /api/auth/link/init (issue short-lived CSRF tokens) - Create DELETE /api/auth/link/:id (ownership check + last-identity guard) - Create GET /api/auth/link/list (list linked accounts) - Create link-token-store.ts: in-process CSRF token store (10-min TTL) - Create LinkedAccountsList.tsx: accessible UI for managing linked accounts Phase 6 - GDPR and polish (T028-T034): - GDPR deletion tests + implementation: delete linked_accounts, anonymise provider_oid/avatar_url/provider/email/name in users table - GDPR export tests + implementation: include linkedAccounts[] in export JSON - Extend ExportFileSchema in community.ts to include linkedAccounts - i18n audit: all strings via AUTH_MESSAGES (zero raw literals) - Accessibility audit: confirmed aria-* attributes and touch targets - Constitution alignment matrix already includes Spec 011 column Tests: 26/26 integration tests passing across 4 test files
…ion format The existing GDPR deletion test expected 'Deleted User' / 'deleted_xxx@system.local' but Spec 011 mandates '[deleted]' for both name and email to be consistent with GDPR anonymization format for all PII fields across the platform.
Done. Merged latest main (v1.5.0 constitution with Principle XIV Managed Identity, Azure deployment infrastructure) into this branch, resolved the Implementation highlights (commit
The spec-kit plan and implementation are complete on this branch ( For the Entra External ID integration specifically, the implementation is environment-agnostic code — the only Azure-specific configuration needed is setting Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot Use spec-kit to plan and implement the Entra external ID stuff. If you're not able to create, give me details of exactly what you need me to create |
…size check, lint error Co-authored-by: MikeWedderburn-Clarke <5323631+MikeWedderburn-Clarke@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/CommunityManagement-Sample-Spec-Kit/sessions/e7d246ae-deca-4e78-8008-aae36255ec77
The Entra External ID implementation from the previous session was complete (34 tasks, 26 integration tests), but the CI was failing. Fixed in commit CI fixes:
All local CI steps now pass: |
…ternal-id-implementation # Conflicts: # .github/workflows/ci.yml # apps/web/src/db/seeds/dev.ts # apps/web/src/lib/auth/config.ts # apps/web/src/lib/config.ts # apps/web/src/lib/gdpr/deletion.ts # apps/web/src/lib/gdpr/full-export.ts # apps/web/src/lib/profiles/service.ts # apps/web/src/lib/teachers/profiles.ts # apps/web/src/proxy.ts # apps/web/tests/integration/community/directory.test.ts # apps/web/tests/integration/community/gdpr.test.ts # apps/web/tests/integration/community/profile-settings-effects.test.ts # apps/web/tests/integration/community/profiles.test.ts # package-lock.json # package.json # packages/shared/src/types/community.ts # packages/shared/src/types/index.ts # specs/constitution.md
…pr-social test expectations Co-authored-by: MikeWedderburn-Clarke <5323631+MikeWedderburn-Clarke@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/CommunityManagement-Sample-Spec-Kit/sessions/1154b6f0-f12a-43ed-a60d-06a677ae2343
|
@copilot CI issues should be fixed now on main. Merge those changes into this branch, fix any issues, and then continue |
…ternal-id-implementation # Conflicts: # .github/workflows/ci.yml
Merged in
All 684/684 tests still pass. |
…tions - infra/main.bicep: add entraClientId, entraTenantId (@secure), entraTenantDomain params - infra/main.parameters.json: bind new params to ENTRA_CLIENT_ID/TENANT_ID/TENANT_DOMAIN env vars - infra/modules/key-vault.bicep: add entra-client-id and entra-tenant-id Key Vault secrets - infra/modules/container-apps.bicep: add Key Vault secret refs (ENTRA_CLIENT_ID, ENTRA_TENANT_ID) and plain env var (ENTRA_TENANT_DOMAIN) - apps/web/src/db/migrate.ts: support MIGRATIONS_DIR env var for bundled runtime path - Dockerfile: compile migrate.ts with esbuild in build stage, add start.sh to run migrations then server - start.sh: new entrypoint script Co-authored-by: MikeWedderburn-Clarke <5323631+MikeWedderburn-Clarke@users.noreply.github.com> Agent-Logs-Url: https://github.com/microsoft/CommunityManagement-Sample-Spec-Kit/sessions/e46b2c7f-7fc7-4498-a63b-ccca2b519eee
infra/main.bicep— addentraClientId,entraTenantId(@secure),entraTenantDomainparams; pass to key-vaultsecretsand container-appsinfra/main.parameters.json— bind the 3 new params to${ENTRA_CLIENT_ID},${ENTRA_TENANT_ID},${ENTRA_TENANT_DOMAIN}env varsinfra/modules/key-vault.bicep— addentra-client-idandentra-tenant-idKey Vault secrets (created conditionally, value taken directly without fallback)infra/modules/container-apps.bicep— add Key Vault secret refs (ENTRA_CLIENT_ID,ENTRA_TENANT_ID) and plain env var (ENTRA_TENANT_DOMAIN)apps/web/src/db/migrate.ts— supportMIGRATIONS_DIRenv var so esbuild bundle can locate SQL files at runtimeDockerfile— compile migration with esbuild, copy SQL files, usestart.shentrypoint (migrations run before server on every container start)start.sh— new entrypoint script checked in as a proper fileOriginal prompt
Created from VS Code.
💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.