v0.1.23 - Make role-as-password the default authorization model; remove interactive approval prompts from wizard; add Makefile guard to direct agents to build_static.sh; optimize build_static.sh with content-hash skip and fix .dockerignore to exclude 1.3GB of unnecessary files from Docker context

This commit is contained in:
Laan Tungir
2026-08-08 08:09:56 -04:00
parent e4087441a5
commit fd895db0c9
5 changed files with 243 additions and 46 deletions
+110
View File
@@ -0,0 +1,110 @@
# Plan: Role-as-Password as the Default Authorization Model
## Status: Draft — ready for review
## Problem
The signer currently defaults to requiring interactive approval for every request, even for the default "main" role. This contradicts the intended design where **knowing the role name is sufficient authorization** (role-as-password). Users running v0.1.21 are prompted to approve requests when they should be authorized automatically.
## Root cause
Three places in the code set `requires_approval = 1` by default:
| Location | Context | Current value |
|---|---|---|
| [`src/main.c:3816`](../src/main.c:3816) | Default "main" role (non-interactive mode) | `requires_approval = 1` |
| [`src/main.c:2374`](../src/main.c:2374) | Wizard role creation prompt | Default `1` (Y/n) |
| [`src/main.c:2223`](../src/main.c:2223) | Wizard OTP role creation prompt | Default `1` (Y/n) |
## Changes required
### 1. Default "main" role — non-interactive mode
**File:** [`src/main.c:3816`](../src/main.c:3816)
Change:
```c
role.requires_approval = 1;
```
To:
```c
role.requires_approval = 0; /* role-as-password: knowing the role name is sufficient */
```
This is the most critical fix — it affects every user running in non-interactive mode (e.g., `--listen unix`, `--listen tcp`, `--listen qrexec`).
### 2. Wizard role creation — remove approval prompt
**File:** [`src/main.c:2359-2377`](../src/main.c:2359)
Currently the wizard asks:
```
Require interactive approval for each request? [Y/n]:
```
With role-as-password as the default, this prompt should be **removed entirely**. The role is created with `requires_approval = 0`. If a user wants approval, they can use `--preapprove` or manually edit the role after creation.
Remove the prompt block (lines 2359-2377) and set:
```c
int requires_approval = 0; /* role-as-password by default */
```
### 3. Wizard OTP role creation — remove approval prompt
**File:** [`src/main.c:2208-2226`](../src/main.c:2208)
Same change as #2. Remove the approval prompt for OTP roles and default to `requires_approval = 0`.
### 4. Policy table default — no change needed
**File:** [`src/policy.c:1097-1113`](../src/policy.c:1097)
The current default policy is `* → PROMPT_EVERY_REQUEST`. This is correct because:
- For roles with `requires_approval = 0`, [`policy_check_with_role()`](../src/policy.c:1305) returns `POLICY_ALLOW` **before** consulting the policy table.
- For roles with `requires_approval = 1`, the policy table prompt still fires as expected.
No change needed here.
### 5. `--allow-all` flag — retain as-is
**File:** [`src/main.c:3678`](../src/main.c:3678)
The `--allow-all` flag sets `g_prompt_always_allow`, which bypasses prompts for algorithm-based verbs (sign, verify, encapsulate, etc.) that don't go through the role system. This is still useful for testing and non-interactive scenarios. No change needed.
## Authorization flow after changes
```mermaid
flowchart TD
A[Client sends request with role name] --> B{Role found?}
B -- No --> C[Reject: unknown_role]
B -- Yes --> D{requires_approval?}
D -- No --> E[Authorize immediately - role-as-password]
D -- Yes --> F[Check policy table]
F --> G{Policy match?}
G -- Allow --> H[Authorize]
G -- Prompt --> I[Show interactive prompt]
G -- Deny --> J[Reject: policy_denied]
I --> K{User choice}
K -- y --> H
K -- a/e --> L[Add session grant] --> H
K -- n --> J
```
## Test impact
- [`tests/test_n_signer_client.sh`](../tests/test_n_signer_client.sh) — may need updates if tests relied on the old approval-required default
- [`tests/test_integration.c`](../tests/test_integration.c) — verify no tests break from the default change
- The `NSIGNER_TEST_FORCE_PROMPT` env var ([`src/main.c:3063`](../src/main.c:3063)) can be used to force prompts in tests that need to exercise the approval path
## Files to modify
| File | Lines | Change |
|---|---|---|
| [`src/main.c`](../src/main.c) | 3816 | `requires_approval = 1``0` |
| [`src/main.c`](../src/main.c) | 2359-2377 | Remove approval prompt, default to `0` |
| [`src/main.c`](../src/main.c) | 2208-2226 | Remove approval prompt, default to `0` |
## Summary
Three one-line changes (plus removing two prompt blocks) to make role-as-password the default. The mechanism already exists in the code — it's just not the default.