Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
**/.DS_Store
**/Thumbs.db
**/assets/wireframes
**/*.log
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ updates:
- /p11-saas-workspace
- /p12-hr-access-governance
- /p13-student-records
- /p14-ai-scheduling-assistant
- /p14-capital-district
- /p15-marketplace
- /shared/identity-provider
schedule:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ jobs:
pnpm install --frozen-lockfile
pnpm build
- name: Install browser and Linux dependencies
if: (matrix.project == 'p1-task-manager' || matrix.project == 'p4-editorial-publishing' || matrix.project == 'p5-dataguard' || matrix.project == 'p6-field-inspection' || matrix.project == 'p7-collaborative-docs' || matrix.project == 'p10-warehouse-workloads' || matrix.project == 'p11-saas-workspace' || matrix.project == 'p14-ai-scheduling-assistant') && runner.os == 'Linux'
if: (matrix.project == 'p1-task-manager' || matrix.project == 'p4-editorial-publishing' || matrix.project == 'p5-dataguard' || matrix.project == 'p6-field-inspection' || matrix.project == 'p7-collaborative-docs' || matrix.project == 'p10-warehouse-workloads' || matrix.project == 'p11-saas-workspace' || matrix.project == 'p14-capital-district' || matrix.project == 'p15-marketplace') && runner.os == 'Linux'
working-directory: ${{ matrix.project }}
run: pnpm exec playwright install --with-deps chromium
- name: Install browser
if: (matrix.project == 'p1-task-manager' || matrix.project == 'p4-editorial-publishing' || matrix.project == 'p5-dataguard' || matrix.project == 'p6-field-inspection' || matrix.project == 'p7-collaborative-docs' || matrix.project == 'p10-warehouse-workloads' || matrix.project == 'p14-ai-scheduling-assistant') && runner.os != 'Linux'
if: (matrix.project == 'p1-task-manager' || matrix.project == 'p4-editorial-publishing' || matrix.project == 'p5-dataguard' || matrix.project == 'p6-field-inspection' || matrix.project == 'p7-collaborative-docs' || matrix.project == 'p10-warehouse-workloads' || matrix.project == 'p14-capital-district' || matrix.project == 'p15-marketplace') && runner.os != 'Linux'
working-directory: ${{ matrix.project }}
run: pnpm exec playwright install chromium
- name: Check
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
*.log
.DS_Store
Thumbs.db
!/p14-capital-district/.dockerignore
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Project links open the setup guides; article links open the published tutorials.
| [P11 - Securing Active-Tenant Switching in a SaaS Workspace with Cedarling](./p11-saas-workspace/) | Node.js, React Router Framework Mode, Express, PostgreSQL | Reevaluate access as users switch tenants, accept invitations, or receive support access. | - |
| [P12 - Governing Employee Record Access with Cedarling](./p12-hr-access-governance/) | Node.js, Express, React, SQLite | Grant and revoke employee-record access while separating requesters from approvers. | - |
| [P13 - Protecting Grade Publication and Guardian Access with Cedarling](./p13-student-records/) | Node.js, Express, React, SQLite | Separate grade editing, publication, student access, and guardian access. | - |
| [P14 - Governing an AI Scheduling Assistant with Cedarling](./p14-ai-scheduling-assistant/) | Node.js, Fastify, React, SQLite | Authorize each scheduling action an assistant proposes before it changes anything. | - |
| [P14 - Authorizing Turns and Property Trades with Cedarling](./p14-capital-district/) | Node.js, Fastify, React, SQLite | Authorize turns, property improvements, and expiring trades using current match facts. | - |
| [P15 - Authorizing a Multi-Party Marketplace Refund with Cedarling](./p15-marketplace/) | Node.js, Express, React, SQLite | Give buyers, sellers, support, and fraud reviewers the right views and refund actions. | - |

## Run the projects your way
Expand Down
2 changes: 1 addition & 1 deletion p1-task-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"tsx": "4.23.12",
"typescript": "6.0.3",
"typescript-eslint": "8.68.0",
"vite": "8.2.2",
"vite": "8.2.4",
"vitest": "4.1.11"
},
"pnpm": {
Expand Down
28 changes: 14 additions & 14 deletions p1-task-manager/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 29 additions & 5 deletions p1-task-manager/src/web/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,37 @@ function ProgramFooter() {
return (
<footer>
<nav aria-label="Related resources">
<a href="https://cedarling.dev">Cedarling.dev</a>
<a href="https://docs.jans.io/stable/cedarling/">Cedarling Docs</a>
<a href="https://gluu.org/agama-lab/">Agama Lab</a>
<a href="https://docs.jans.io/stable/cedarling/reference/cedarling-lock-server/">
<a
href="https://cedarling.dev"
target="_blank"
rel="noopener noreferrer"
>
Cedarling.dev
</a>
<a
href="https://docs.jans.io/stable/cedarling/"
target="_blank"
rel="noopener noreferrer"
>
Cedarling Docs
</a>
<a
href="https://gluu.org/agama-lab/"
target="_blank"
rel="noopener noreferrer"
>
Agama Lab
</a>
<a
href="https://docs.jans.io/stable/cedarling/reference/cedarling-lock-server/"
target="_blank"
rel="noopener noreferrer"
>
Lock Server
</a>
<a href="https://gluu.org">Gluu</a>
<a href="https://gluu.org" target="_blank" rel="noopener noreferrer">
Gluu
</a>
</nav>
</footer>
);
Expand Down
7 changes: 0 additions & 7 deletions p10-warehouse-workloads/.dockerignore

This file was deleted.

123 changes: 63 additions & 60 deletions p10-warehouse-workloads/README.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,111 @@
# P10 - Authorizing Warehouse Workloads with Cedarling

P10 is a warehouse stock-transfer console for learning how Cedarling authorizes
OAuth Client Credentials workloads. A signed machine token proves which
workload is calling; authorization decides whether that workload may plan,
release, receive, or inspect a transfer in its current state.
P10 moves stock between two warehouses. Its console sends commands through
four workload agents, each authenticated with OAuth Client Credentials.

The marked capabilities currently use compact fake permissive decisions. The
Cedarling tutorial replaces that adapter while preserving every business and
authentication boundary.
The learning baseline validates workload tokens and requests, while business
permissions return `FAKE ALLOW`. Cedarling will restrict each workload to its
warehouse and operation.

## Architecture

```text
React workload console
│ fixed workload action
▼
Console BFF ── private credential ──► Workload agent ── Client Credentials ──► IdP
│ signed access token
▼
Warehouse API (PEP)
│ principal + current SQLite facts
▼
Cedarling
│ │
DENY ALLOW ──► conditional SQLite effect
```mermaid
flowchart TD
Browser["React workload console"] --> BFF["Console BFF"]
BFF -->|Private control request| Agents["Four isolated workload agents"]
Agents -->|Client Credentials| IdP["Tutorial IdP"]
Agents -->|Signed access token| API["Warehouse API"]
API --> Fake["FAKE ALLOW"]
Fake --> DB["Conditional inventory and transfer transaction"]
```

The browser never receives a client secret or workload token. Four isolated
agent processes each own one credential. The Warehouse API verifies the token,
loads current transfer and inventory facts, marks the authorization boundary,
and only then attempts a versioned SQLite transaction.

## Prerequisites

- Docker Desktop or Docker Engine with Compose, or
- Node.js 24.21 or newer within 24.x, pnpm 10, and the project-local tutorial identity provider.

The commands work from PowerShell, macOS terminals, and Ubuntu shells.
- Docker Desktop or Docker Engine with Compose.
- Node.js 24.21 or newer within 24.x.
- pnpm 10.17.1.

## Run

Start the application and its own IdP:
From this project directory, start with Docker:

```bash
docker compose up --build
```

Open <http://localhost:17010>. The issuer is <http://localhost:18010>. Stop the stack with `Ctrl+C`, then `docker compose down`.
Open <http://localhost:17010>. The tutorial IdP is <http://localhost:18010>.
Stop with `Ctrl+C`, then `docker compose down`.

For native development, run from this project directory:
For native development:

```bash
pnpm --dir ../shared/identity-provider install --frozen-lockfile
pnpm --dir ../shared/identity-provider build
pnpm install --frozen-lockfile
pnpm run setup
pnpm dev
```

`pnpm dev` starts this project’s IdP and application together.
`pnpm dev` prepares configuration and starts the IdP, Warehouse API, four
agents, and console. Refresh after a browser-source rebuild.
The console uses workload identities and opens directly.

## Exercise

`pnpm build` followed by `pnpm start` runs the compiled application stack and its project IdP.
The workloads have these intended responsibilities:

Use `pnpm dev -- --reset` only when you want to restore the tutorial fixtures.
- Transfer Planner creates transfers.
- North Warehouse releases North stock and receives North deliveries.
- South Warehouse releases South stock and receives South deliveries.
- Inventory Auditor reads inventory.

## Exercise
Choose **New transfer**, select North to South, choose an item and quantity,
then create it as Planner. Release it as North, then receive it as South.
Planning leaves stock unchanged; release deducts from the source and receipt
adds to the destination.

Repeat with a new transfer. Use **Try another workload** at each step:

The workflow moves three allowlisted products between North and South
warehouses:
1. Create as Auditor despite its read-only responsibility.
2. Release North's stock as South.
3. Receive the South-bound delivery as North.

- **Transfer Planner** — creates and inspects planned transfers.
- **North Warehouse** — releases North stock and receives North deliveries.
- **South Warehouse** — releases South stock and receives South deliveries.
- **Inventory Auditor** — reads inventory without changing transfers.
All three operations succeed in the baseline. Stock, transfer-state, and version
checks still apply.

Create a North-to-South transfer as Planner. Release it as North, receive it as
South, and confirm that stock moves exactly once at each transition. Then use
the secondary actions to reproduce the three authorization problems:
## Data and reset

- Auditor creates a transfer despite being read-only.
- South releases stock owned by North.
- North receives stock destined for South.
Restarts preserve your changes. For native data, stop the app, run
`pnpm reset`, then `pnpm dev`. Reset restores stock and removes transfers and
retry records.

Cedarling will deny those three operations from the same authenticated
workloads while retaining the valid Planner, source-warehouse,
destination-warehouse, and Auditor reads.
For the default Docker setup:

```bash
docker compose down
docker volume rm p10-warehouse-workloads_p10-data
docker compose up --build
```

This removes application data and preserves IdP credentials. Custom Compose
project names or data mounts require their corresponding data target.

## Commands

| Command | Purpose |
| --- | --- |
| `pnpm run setup` | Synchronize workload credentials and initialize SQLite |
| `pnpm dev` | Build and run the watched native stack |
| `pnpm start` | Build and run the production-mode native stack |
| `pnpm reset` | Restore deterministic inventory and transfer fixtures |
| `pnpm run setup` | Prepare workload credentials and inventory |
| `pnpm start` | Build and run the complete native stack |
| `pnpm test:e2e` | Exercise the workload console in Chromium |
| `pnpm check` | Run formatting, lint, types, tests, build, and browser checks |

## Verify

Install Chromium once before the complete local check:
Stop this project's running stack before checking local changes. `pnpm check`
runs formatting, lint, type checks, tests, build, and browser checks using
disposable data. Install Chromium once:

```bash
pnpm exec playwright install chromium
pnpm check
pnpm audit --audit-level low
```

On Linux, add `--with-deps` to the Chromium installation command if system
libraries are missing.
3 changes: 2 additions & 1 deletion p10-warehouse-workloads/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ services:
test:
- CMD
- node
- --env-file=/run/config/.env
- -e
- fetch('http://127.0.0.1:18010/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))
- fetch('http://127.0.0.1:18010/.well-known/openid-configuration').then(async r=>process.exit(r.ok&&(await r.json()).issuer===process.env.IDP_ISSUER?0:1)).catch(()=>process.exit(1))
interval: 2s
timeout: 3s
retries: 30
Expand Down
Loading
Loading