[Spec Kit] Implementation progress

This commit is contained in:
2026-04-22 19:41:14 -05:00
parent 24cfd85ac2
commit 110c2e961b
61 changed files with 5371 additions and 38 deletions

View File

@@ -0,0 +1,113 @@
# Contract: Proxy HTTP Responses
**Feature**: 001-oidc-proxy-script
**File**: `src/proxyScripts/proxy.js`
**Endpoint**: Any path handled by the adapter (all requests delegated to proxy.js by server.js)
**Date**: 2025-07-17
---
## Overview
`proxy.js` responds to every inbound HTTP request with exactly one of two outcomes:
a success response (authentication succeeded) or an error response (authentication failed for
any reason). The contract defines the exact shape of both outcomes.
---
## Success Response
**Trigger**: OIDC token successfully obtained (fresh fetch or valid cached token).
```
HTTP/1.1 200 OK
Content-Type: text/plain
Authorized
```
| Property | Value |
|----------|-------|
| Status code | `200` |
| Status text | `OK` |
| `Content-Type` header | `text/plain` |
| Body | Literal string `Authorized` (no trailing newline) |
**Acceptance test** (FR-007, SC-001, SC-002):
```javascript
assert.strictEqual(res.statusCode, 200);
assert.strictEqual(res.body, 'Authorized');
```
---
## Error Response
**Trigger**: Any of the following (FR-008, SC-004):
- Token service returns HTTP 4xx or 5xx
- Token service is unreachable (network error)
- Token request times out after 5 seconds (FR-014)
- Token service response is missing `id_token` or `expires_in`
- `adapter_settings` is missing a required field
```
HTTP/1.1 401 Unauthorized
Content-Type: text/plain
Unauthorized: <descriptive message>
```
| Property | Value |
|----------|-------|
| Status code | `401` |
| Status text | `Unauthorized` |
| `Content-Type` header | `text/plain` |
| Body prefix | `Unauthorized: ` (literal, followed by the error message) |
| Body | Never empty; always includes a human-readable description |
**Example bodies by error cause**:
| Cause | Example body |
|-------|-------------|
| Invalid credentials (401 from token service) | `Unauthorized: HTTP 401` |
| Token service unavailable | `Unauthorized: connect ECONNREFUSED 127.0.0.1:443` |
| 5-second timeout | `Unauthorized: token service timeout` |
| Response missing `id_token` | `Unauthorized: id_token missing from response` |
| Response missing `expires_in` | `Unauthorized: expires_in missing from response` |
| Missing `tokenUrl` in settings | `Unauthorized: missing required field: tokenUrl` |
**Acceptance test** (FR-008):
```javascript
assert.strictEqual(res.statusCode, 401);
assert.match(res.body, /^Unauthorized: .+/);
```
---
## Invariants
These MUST hold for every request, regardless of outcome:
1. **One response per request**: `res.writeHead()` MUST be called exactly once;
`res.end()` MUST be called exactly once.
2. **Never 500**: `proxy.js` MUST NOT emit a 500 or leave the connection open. All
errors, including unexpected runtime errors, MUST result in a `401` (not a crash or hang).
3. **No imports/exports** (FR-009): The script MUST contain zero `import` or `export`
statements — verified by static analysis.
4. **No forbidden globals** (FR-010): No `config`, `global.config`, or `process.env`
references — verified by static analysis.
5. **Response within 5 seconds** (SC-001, FR-014): The HTTP timeout on the token POST
is 5 000 ms. Combined with synchronous error handling, every request resolves within
5 seconds under normal network conditions.
---
## Out of Scope
- The proxy script does NOT validate the inbound request (method, path, headers, body).
Its sole responsibility is OIDC authentication.
- The response does NOT include the OIDC token in the body. The `200 OK / Authorized`
body is sufficient to confirm authentication succeeded (spec assumption, line 106).
- No `Authorization` response header is set. The adapter's caller does not require it.