Skip to content

Commit a0a34a9

Browse files
ScottArbeitScott Arbeit
andauthored
Grace CLI Authentication with Personal Access Tokens and Device Code Login (with Maximum Token Lifetime) (#40)
* feat: add authz types and initialize beads tracking * chore: remove src beads directory * feat: add shared authorization evaluation * feat: add access control and repo permission actors * feat: add test auth and permission evaluator * feat: add access API parameters and routes * feat: add access SDK * feat: add access CLI commands * feat: enforce authz on repo and storage endpoints * test: add authz unit and integration coverage * fix: authz serialization and test setup * fix: remove obsolete ISystemClock usage * docs: update bd usage in AGENTS * fix: retry access control persistence on transient storage errors * feat: add auth config and claim mapping * chore: close auth config task * feat: add auth login endpoints * chore: close auth login task * feat: wire microsoft oidc and jwt auth * chore: close auth scheme task * feat: add cli device code auth and sdk token support * test: cover auth endpoints and cli auth configuration * docs: add microsoft auth setup guide * fix: force OIDC code flow for Microsoft auth * fix: set OIDC response type literal to avoid missing constant * fix: accept tenant-specific issuer for Microsoft auth * fix: use IssuerValidator delegate for Microsoft auth * fix: skip Microsoft userinfo call without Graph scope * feat: request Graph scope and enable userinfo claims * fix: ensure scope sent during OIDC code redemption * fix: avoid mixing Graph and API scopes in OIDC * feat: return raw auth claims from /auth/me * Add REPO_INDEX.md * Add PAT auth flow and improve Aspire auth wiring --------- Co-authored-by: Scott Arbeit <scottarbeit@github.com>
1 parent ae311fc commit a0a34a9

File tree

77 files changed

+5383
-46
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+5383
-46
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ daemon.lock
1010
daemon.log
1111
daemon.pid
1212
bd.sock
13+
sync-state.json
14+
15+
# Local version tracking (prevents upgrade notification spam after git ops)
16+
.local_version
1317

1418
# Legacy database files
1519
db.sqlite
@@ -25,5 +29,6 @@ beads.right.meta.json
2529

2630
# Keep JSONL exports and config (source of truth for git)
2731
!issues.jsonl
32+
!interactions.jsonl
2833
!metadata.json
2934
!config.json
File renamed without changes.

.beads/issues.jsonl

Lines changed: 43 additions & 0 deletions
Large diffs are not rendered by default.

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
# Use bd merge for beads JSONL files
3+
.beads/issues.jsonl merge=beads

AGENTS.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Agent Instructions
2+
3+
This project uses **bd** (beads) for issue tracking. The repo is initialized at the root `.beads`, so run `bd` from the repo root.
4+
5+
## Quick Reference
6+
7+
```bash
8+
bd ready --json # Find available work (ready issues)
9+
bd list --parent <epic-id> # List child tasks for an epic (use this; there is no "bd tasks")
10+
bd show <id> # View issue details
11+
bd update <id> --status in_progress # Claim work
12+
bd close <id> # Complete work
13+
bd sync # Sync with git (when using JSONL sync)
14+
bd --help # Command reference (recommended)
15+
```
16+
17+
## Landing the Plane (Session Completion)
18+
19+
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
20+
21+
**MANDATORY WORKFLOW:**
22+
23+
1. **File issues for remaining work** - Create issues for anything that needs follow-up
24+
2. **Run quality gates** (if code changed) - Tests, linters, builds
25+
3. **Update issue status** - Close finished work, update in-progress items
26+
4. **PUSH TO REMOTE** - This is MANDATORY:
27+
```bash
28+
git pull --rebase
29+
bd sync
30+
git push
31+
git status # MUST show "up to date with origin"
32+
```
33+
5. **Clean up** - Clear stashes, prune remote branches
34+
6. **Verify** - All changes committed AND pushed
35+
7. **Hand off** - Provide context for next session
36+
37+
**CRITICAL RULES:**
38+
- Work is NOT complete until `git push` succeeds
39+
- NEVER stop before pushing - that leaves work stranded locally
40+
- NEVER say "ready to push when you are" - YOU must push
41+
- If push fails, resolve and retry until it succeeds

REPO_INDEX.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# REPO_INDEX.md (Grace jump table)
2+
3+
This file is a machine-oriented index to help tools and humans quickly find the right code.
4+
5+
---
6+
7+
## Suggested search strategy for AllGrace.txt
8+
9+
1. Refer to AllGrace_Index.md for exact starting and ending line numbers for each file.
10+
2. Use the entry points list below to decide where to navigate to.
11+
3. Jump to the exact starting line of the file, and search within the starting and ending line numbers.
12+
13+
## Top entry points (open these first)
14+
15+
### Grace Server (HTTP + DI + Orleans wiring)
16+
17+
- `src/Grace.Server/Startup.Server.fs`
18+
HTTP routes/endpoints and server composition entry points.
19+
- `src/Grace.Server/Program.Server.fs`
20+
Host startup (Kestrel/Orleans host build/run).
21+
22+
### Orleans grains (domain behavior)
23+
24+
- `src/Grace.Actors/**/*.fs`
25+
Grain/actor implementations. Look for `*Actor.fs` as primary behavior files.
26+
27+
### Domain types, events, DTOs
28+
29+
- `src/Grace.Types/**/*.fs`
30+
Discriminated unions, events, DTOs, identifiers, serialization shapes.
31+
32+
### Local orchestration (emulators/containers)
33+
34+
- `src/Grace.Aspire.AppHost/Program.Aspire.AppHost.cs`
35+
Local dev topology: Cosmos emulator, Azurite, Service Bus emulator, Redis, and Grace.Server.
36+
37+
### Integration tests
38+
39+
- `src/Grace.Server.Tests/General.Server.Tests.fs`
40+
Test harness bootstrapping and shared test state.
41+
- `src/Grace.Server.Tests/Owner.Server.Tests.fs`
42+
Owner API tests.
43+
- `src/Grace.Server.Tests/Repository.Server.Tests.fs`
44+
Repository API tests.
45+
46+
---
47+
48+
## Cross-cutting �where is X implemented?�
49+
50+
### JSON serialization settings
51+
52+
- Search: `JsonSerializerOptions`
53+
- Likely in: `src/Grace.Shared/**` or `src/Grace.Server/**`
54+
55+
### Service Bus publishing
56+
57+
- Search: `publishGraceEvent`, `ServiceBusMessage`, `GraceEvent`
58+
- Likely in:
59+
- `src/Grace.Actors/**` (where events are emitted)
60+
- `src/Grace.Server/**` (wiring/config)
61+
- `src/Grace.Shared/**` (helpers)
62+
63+
### Cosmos DB / persistence wiring
64+
65+
- Search: `AddCosmosGrainStorage`, `CosmosClient`, `UseAzureStorageClustering`
66+
- Likely in: `src/Grace.Server/Startup.Server.fs`
67+
68+
### Azure Blob grain storage
69+
70+
- Search: `AddAzureBlobGrainStorage`, `BlobServiceClient`
71+
- Likely in: `src/Grace.Server/Startup.Server.fs`
72+
73+
### CLI commands
74+
75+
- Search: `grace owner create`, `Command`, `System.CommandLine`
76+
- Likely in: `src/Grace.CLI/**`
77+
78+
---
79+
80+
## Local development �source of truth�
81+
82+
- Aspire AppHost defines the runnable local environment. If there is a discrepancy between older docs/tests and AppHost, prefer AppHost.
83+
84+
---
85+
86+
## Obsolete / legacy systems
87+
88+
- Dapr is not used anymore. Any Dapr references in tests or tooling are legacy and should be removed or ignored.

docs/Authentication.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Authentication (Microsoft MSA + Entra)
2+
3+
Grace currently supports Microsoft identity for both web and CLI clients. This uses:
4+
- A **web app registration** for the Grace Server (confidential client).
5+
- A **public client app registration** for Grace CLI (device code flow).
6+
7+
GitHub and Google sign-in are planned but not yet implemented. The `/auth/login` page will list those providers once configured.
8+
9+
## App Registrations (Azure Portal)
10+
11+
### 1) Grace Server (Web app, confidential client)
12+
1. Create a new **App registration** (Accounts: "Accounts in any organizational directory and personal Microsoft accounts").
13+
2. Add a **Web** redirect URI for your server:
14+
- Local dev: `https://localhost:5001/signin-oidc` (or your local HTTPS port).
15+
- Deployed: `https://<your-domain>/signin-oidc`.
16+
3. Create a **Client secret** (Certificates & secrets).
17+
4. **Expose an API**:
18+
- Application ID URI: `api://<server-client-id>` (or your preferred URI).
19+
- Add scope: `access`.
20+
21+
This produces:
22+
- Server **Client ID**
23+
- Server **Client Secret**
24+
- API scope: `api://<server-client-id>/access` (default used by Grace)
25+
26+
### 2) Grace CLI (Public client)
27+
1. Create a new **App registration** (same account type as above).
28+
2. Add a **Mobile and desktop** redirect URI:
29+
- `http://localhost` (device code flow does not rely on redirect, but this is commonly used).
30+
3. **API permissions**:
31+
- Add delegated permission for the server API scope: `access`.
32+
- Grant admin consent if required by your tenant.
33+
34+
This produces:
35+
- CLI **Client ID**
36+
37+
## Environment Variables
38+
39+
### Grace Server
40+
Required:
41+
- `grace__auth__microsoft__client_id` = Server Client ID
42+
- `grace__auth__microsoft__client_secret` = Server Client Secret
43+
44+
Optional:
45+
- `grace__auth__microsoft__tenant_id` = Tenant ID (default: `common`)
46+
- `grace__auth__microsoft__authority` = Authority override (default: `https://login.microsoftonline.com/{tenant_id}`)
47+
- `grace__auth__microsoft__api_scope` = API scope override (default: `api://{client_id}/access`)
48+
- `grace__auth__microsoft__cli_client_id` = CLI Client ID (optional but recommended to keep in the same config)
49+
50+
### Grace CLI
51+
Required:
52+
- `grace__auth__microsoft__cli_client_id` = CLI Client ID
53+
- `grace__auth__microsoft__api_scope` = API scope (ex: `api://<server-client-id>/access`)
54+
55+
Optional:
56+
- `grace__auth__microsoft__tenant_id` = Tenant ID (default: `common`)
57+
- `grace__auth__microsoft__authority` = Authority override
58+
59+
## Using the Web Login
60+
61+
- Browse to `https://<server>/auth/login`
62+
- Choose **Microsoft**
63+
- A cookie session is established after successful login.
64+
65+
## Using the CLI (Device Code)
66+
67+
Common commands:
68+
- `grace auth login` (device code sign-in)
69+
- `grace auth status`
70+
- `grace auth whoami`
71+
- `grace auth logout`
72+
73+
Tokens are cached using MSAL in:
74+
- `~/.grace/grace_msal_cache.bin`
75+
76+
Grace CLI attaches the Bearer token automatically for SDK calls once authenticated.
77+
78+
## Future Providers (GitHub, Google)
79+
80+
GitHub and Google providers are not wired yet. When added, they will appear in `/auth/login` with additional environment variables and app registration steps.

0 commit comments

Comments
 (0)