arcane-cli 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/assets/.arcane/agents/agent-policies-template.md +414 -0
- package/dist/assets/.arcane/governance/agent-approved-paths.md +60 -0
- package/dist/assets/.arcane/governance/agent-policies.md +414 -0
- package/dist/assets/.arcane/governance/agent-work-queue-model.md +61 -0
- package/dist/assets/.arcane/governance/authentication-strategy.md +220 -0
- package/dist/assets/.arcane/governance/cicd-standards.md +227 -0
- package/dist/assets/.arcane/governance/decision-documentation-standard.md +335 -0
- package/dist/assets/.arcane/governance/development-methodology.md +384 -0
- package/dist/assets/.arcane/governance/git-conventions.md +759 -0
- package/dist/assets/.arcane/governance/hardening-checklist.md +117 -0
- package/dist/assets/.arcane/governance/naming-conventions.md +142 -0
- package/dist/assets/.arcane/governance/new-business-setup.md +182 -0
- package/dist/assets/.arcane/governance/poc-management-pattern.md +190 -0
- package/dist/assets/.arcane/governance/portable-bootstrap.md +101 -0
- package/dist/assets/.arcane/governance/product-excellence-standards.md +211 -0
- package/dist/assets/.arcane/governance/rca-process-standard.md +157 -0
- package/dist/assets/.arcane/governance/spell-authoring-standards.md +129 -0
- package/dist/assets/.arcane/governance/testing-standards.md +158 -0
- package/dist/assets/.arcane/governance/threat-model.md +104 -0
- package/dist/assets/.arcane/governance/universal-agent-rules.md +108 -0
- package/dist/assets/.arcane/image-prompts/adelaide-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/alexander-image-prompt.md +138 -0
- package/dist/assets/.arcane/image-prompts/bess-image-prompt.md +139 -0
- package/dist/assets/.arcane/image-prompts/circe-image-prompt.md +143 -0
- package/dist/assets/.arcane/image-prompts/custodio-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/iris-image-prompt.md +139 -0
- package/dist/assets/.arcane/image-prompts/kellar-image-prompt.md +141 -0
- package/dist/assets/.arcane/image-prompts/lafayette-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/lince-image-prompt.md +142 -0
- package/dist/assets/.arcane/image-prompts/mercurio-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/merlin-image-prompt.md +139 -0
- package/dist/assets/.arcane/image-prompts/prospero-image-prompt.md +141 -0
- package/dist/assets/.arcane/templates/venture-template/overview.md +66 -0
- package/dist/assets/.claude/commands/spell-address-review.md +9 -0
- package/dist/assets/.claude/commands/spell-arcane-version.md +9 -0
- package/dist/assets/.claude/commands/spell-architect.md +9 -0
- package/dist/assets/.claude/commands/spell-bootstrap-business.md +9 -0
- package/dist/assets/.claude/commands/spell-brainstorm.md +9 -0
- package/dist/assets/.claude/commands/spell-bug.md +9 -0
- package/dist/assets/.claude/commands/spell-bump.md +9 -0
- package/dist/assets/.claude/commands/spell-check-drift.md +9 -0
- package/dist/assets/.claude/commands/spell-close-session.md +9 -0
- package/dist/assets/.claude/commands/spell-commit-work.md +9 -0
- package/dist/assets/.claude/commands/spell-create-pull-request.md +9 -0
- package/dist/assets/.claude/commands/spell-document.md +9 -0
- package/dist/assets/.claude/commands/spell-dotnet-expert.md +9 -0
- package/dist/assets/.claude/commands/spell-eas-ios-deploy.md +9 -0
- package/dist/assets/.claude/commands/spell-enchant.md +9 -0
- package/dist/assets/.claude/commands/spell-explain-concept.md +9 -0
- package/dist/assets/.claude/commands/spell-feedback.md +9 -0
- package/dist/assets/.claude/commands/spell-full-cycle.md +9 -0
- package/dist/assets/.claude/commands/spell-generate-bot-icons.md +9 -0
- package/dist/assets/.claude/commands/spell-implement.md +9 -0
- package/dist/assets/.claude/commands/spell-open-session.md +9 -0
- package/dist/assets/.claude/commands/spell-plan.md +9 -0
- package/dist/assets/.claude/commands/spell-present-arcane.md +9 -0
- package/dist/assets/.claude/commands/spell-product-review.md +9 -0
- package/dist/assets/.claude/commands/spell-review-batch.md +9 -0
- package/dist/assets/.claude/commands/spell-review.md +9 -0
- package/dist/assets/.claude/commands/spell-save-idea.md +9 -0
- package/dist/assets/.claude/commands/spell-scope.md +9 -0
- package/dist/assets/.claude/commands/spell-security-review.md +9 -0
- package/dist/assets/.claude/commands/spell-ship.md +9 -0
- package/dist/assets/.claude/commands/spell-status.md +9 -0
- package/dist/assets/.claude/commands/spell-suggest-feature.md +9 -0
- package/dist/assets/.claude/commands/spell-test.md +9 -0
- package/dist/assets/.claude/commands/spell-todo.md +9 -0
- package/dist/assets/.github/agents/adelaide.agent.md +44 -0
- package/dist/assets/.github/agents/alexander.agent.md +43 -0
- package/dist/assets/.github/agents/bess.agent.md +42 -0
- package/dist/assets/.github/agents/circe.agent.md +43 -0
- package/dist/assets/.github/agents/custodio.agent.md +44 -0
- package/dist/assets/.github/agents/iris.agent.md +43 -0
- package/dist/assets/.github/agents/kellar.agent.md +43 -0
- package/dist/assets/.github/agents/lafayette.agent.md +42 -0
- package/dist/assets/.github/agents/lince.agent.md +43 -0
- package/dist/assets/.github/agents/mercurio.agent.md +43 -0
- package/dist/assets/.github/agents/merlin.agent.md +44 -0
- package/dist/assets/.github/agents/prospero.agent.md +43 -0
- package/dist/assets/.github/instructions/agent-output.instructions.md +48 -0
- package/dist/assets/.github/prompts/spell-address-review.prompt.md +114 -0
- package/dist/assets/.github/prompts/spell-arcane-version.prompt.md +82 -0
- package/dist/assets/.github/prompts/spell-architect.prompt.md +116 -0
- package/dist/assets/.github/prompts/spell-bootstrap-business.prompt.md +73 -0
- package/dist/assets/.github/prompts/spell-brainstorm.prompt.md +124 -0
- package/dist/assets/.github/prompts/spell-bug.prompt.md +109 -0
- package/dist/assets/.github/prompts/spell-bump.prompt.md +73 -0
- package/dist/assets/.github/prompts/spell-check-drift.prompt.md +97 -0
- package/dist/assets/.github/prompts/spell-close-session.prompt.md +189 -0
- package/dist/assets/.github/prompts/spell-commit-work.prompt.md +211 -0
- package/dist/assets/.github/prompts/spell-create-pull-request.prompt.md +170 -0
- package/dist/assets/.github/prompts/spell-document.prompt.md +83 -0
- package/dist/assets/.github/prompts/spell-dotnet-expert.prompt.md +117 -0
- package/dist/assets/.github/prompts/spell-eas-ios-deploy.prompt.md +183 -0
- package/dist/assets/.github/prompts/spell-enchant.prompt.md +385 -0
- package/dist/assets/.github/prompts/spell-explain-concept.prompt.md +69 -0
- package/dist/assets/.github/prompts/spell-feedback.prompt.md +113 -0
- package/dist/assets/.github/prompts/spell-full-cycle.prompt.md +201 -0
- package/dist/assets/.github/prompts/spell-generate-bot-icons.prompt.md +84 -0
- package/dist/assets/.github/prompts/spell-implement.prompt.md +101 -0
- package/dist/assets/.github/prompts/spell-open-session.prompt.md +116 -0
- package/dist/assets/.github/prompts/spell-plan.prompt.md +145 -0
- package/dist/assets/.github/prompts/spell-present-arcane.prompt.md +188 -0
- package/dist/assets/.github/prompts/spell-product-review.prompt.md +97 -0
- package/dist/assets/.github/prompts/spell-review-batch.prompt.md +94 -0
- package/dist/assets/.github/prompts/spell-review.prompt.md +131 -0
- package/dist/assets/.github/prompts/spell-save-idea.prompt.md +83 -0
- package/dist/assets/.github/prompts/spell-scope.prompt.md +263 -0
- package/dist/assets/.github/prompts/spell-security-review.prompt.md +129 -0
- package/dist/assets/.github/prompts/spell-ship.prompt.md +104 -0
- package/dist/assets/.github/prompts/spell-status.prompt.md +85 -0
- package/dist/assets/.github/prompts/spell-suggest-feature.prompt.md +110 -0
- package/dist/assets/.github/prompts/spell-test.prompt.md +87 -0
- package/dist/assets/.github/prompts/spell-todo.prompt.md +126 -0
- package/dist/assets/DECISIONS.md +19 -0
- package/dist/assets/TODO.md +7 -0
- package/dist/assets/agents/architecture-lead.yaml +61 -0
- package/dist/assets/agents/collaborator.yaml +59 -0
- package/dist/assets/agents/devops.yaml +60 -0
- package/dist/assets/agents/frontend-dev.yaml +60 -0
- package/dist/assets/agents/fullstack-dev.yaml +59 -0
- package/dist/assets/agents/marketing-strategist.yaml +60 -0
- package/dist/assets/agents/mobile-dev.yaml +59 -0
- package/dist/assets/agents/operations-comms.yaml +58 -0
- package/dist/assets/agents/orchestrator.yaml +60 -0
- package/dist/assets/agents/qa-lead.yaml +60 -0
- package/dist/assets/agents/research-analyst.yaml +59 -0
- package/dist/assets/agents/security-ops.yaml +61 -0
- package/dist/assets/ai-context/system-prompt-context.md +32 -0
- package/dist/assets/journal/.gitkeep +0 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +2313 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Authentication Strategy
|
|
3
|
+
audience: both
|
|
4
|
+
last_updated: YYYY-MM-DD
|
|
5
|
+
status: active
|
|
6
|
+
distributable: true
|
|
7
|
+
tags: [security, authentication, credentials, ssh, api-keys]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Authentication Strategy
|
|
11
|
+
|
|
12
|
+
This document provides rationale for authentication decisions across an agent runtime's operational infrastructure. It is vendor-neutral: apply the principles to whichever runtime, Git host, and model provider you use.
|
|
13
|
+
|
|
14
|
+
## Executive Summary
|
|
15
|
+
|
|
16
|
+
- Authentication follows defense in depth: network isolation + credential controls + audit logging.
|
|
17
|
+
- Git access uses SSH keys instead of bearer tokens (PATs) to reduce replay exposure.
|
|
18
|
+
- Model-provider and gateway secrets use a secret-reference pattern (env var / secret manager), not plaintext in config files.
|
|
19
|
+
- This file is the single detailed reference for "why this auth choice over alternatives."
|
|
20
|
+
|
|
21
|
+
## Principles
|
|
22
|
+
|
|
23
|
+
**1. Minimize Bearer Token Exposure**
|
|
24
|
+
- Bearer tokens (PATs, API keys) can be replayed if intercepted once
|
|
25
|
+
- Prefer challenge/response authentication (SSH, OAuth) when available
|
|
26
|
+
- When bearer tokens are required, store them as environment variables via a secret-reference pattern
|
|
27
|
+
|
|
28
|
+
**2. Credential Isolation**
|
|
29
|
+
- Each service/agent uses separate credentials with minimal required scope
|
|
30
|
+
- Credentials stored outside version control (`.env`, system keychains, secret managers)
|
|
31
|
+
- Rotation/revocation must be straightforward without config file changes
|
|
32
|
+
|
|
33
|
+
**3. Defense in Depth**
|
|
34
|
+
- Authentication is one layer; combine with network isolation (loopback bind, VPN/tunnel)
|
|
35
|
+
- Audit logging for all credential operations
|
|
36
|
+
- Regular review of active credentials and permissions
|
|
37
|
+
|
|
38
|
+
## Authentication Contexts
|
|
39
|
+
|
|
40
|
+
### Git Operations
|
|
41
|
+
|
|
42
|
+
**Decision:** SSH key pairs for agent automation
|
|
43
|
+
|
|
44
|
+
**Mechanism:**
|
|
45
|
+
- An SSH key pair generated on the agent host (prefer Ed25519; fall back to RSA 4096 if the host rejects Ed25519)
|
|
46
|
+
- Public key registered with the Git host
|
|
47
|
+
- Private key remains local at `~/.ssh/id_*` (`600` permissions)
|
|
48
|
+
- Git remote configured to use the SSH URL
|
|
49
|
+
|
|
50
|
+
**Why SSH Over PAT:**
|
|
51
|
+
|
|
52
|
+
1. **Bearer Token Replay Risk**
|
|
53
|
+
- PATs are bearer tokens: if exposed once (leaked in logs, environment dumps, shell history), they can be replayed until expiration or manual revocation
|
|
54
|
+
- SSH authentication uses private-key challenge/response; the private key never leaves the local machine
|
|
55
|
+
- Intercepting SSH traffic doesn't expose the private key (only the public key and an encrypted challenge)
|
|
56
|
+
|
|
57
|
+
2. **Reduced Secret Exposure Surface**
|
|
58
|
+
- PATs must be embedded in Git URLs (`https://token@host/...`), shell commands, or environment variables
|
|
59
|
+
- This increases exposure in process lists, command history, debug logs, and automation scripts
|
|
60
|
+
- SSH keys are referenced by Git automatically; no secret in the command line or URLs
|
|
61
|
+
|
|
62
|
+
3. **Simplified Rotation Model**
|
|
63
|
+
- Rotating a PAT requires updating everywhere it's stored (environment files, config files, CI/CD secrets)
|
|
64
|
+
- Rotating SSH keys: generate a new pair, upload the new public key, revoke the old one
|
|
65
|
+
- Private-key rotation doesn't require updating config files (Git uses `~/.ssh/id_*` by convention)
|
|
66
|
+
|
|
67
|
+
4. **Consistent with Industry Practice**
|
|
68
|
+
- GitHub, GitLab, Bitbucket, and Azure DevOps all support SSH for automation over HTTPS+PAT
|
|
69
|
+
- SSH is the standard for CI/CD systems
|
|
70
|
+
- Git and OpenSSH have decades of hardening against SSH key compromise
|
|
71
|
+
|
|
72
|
+
5. **ACL Enforcement Still Applies**
|
|
73
|
+
- SSH authentication doesn't bypass host-side permissions
|
|
74
|
+
- Repository access, branch policies, and project-level ACLs are still enforced
|
|
75
|
+
- The SSH key is tied to a user identity; audit logs show the authenticated user, not an anonymous token
|
|
76
|
+
|
|
77
|
+
**Trade-offs:**
|
|
78
|
+
- SSH requires initial key generation and registration (one-time setup)
|
|
79
|
+
- PATs offer time-based auto-expiration; SSH keys don't expire (must be manually rotated)
|
|
80
|
+
- **Chosen:** SSH's reduced exposure risk outweighs the PAT's auto-expiration convenience
|
|
81
|
+
|
|
82
|
+
**Implementation Notes:**
|
|
83
|
+
- Prefer Ed25519 keys; some hosts may reject them, in which case use RSA 4096-bit
|
|
84
|
+
- If a private key cannot be passphrase-protected (unattended agent automation), rely on filesystem permissions (`600`) and OS-level security
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### Model Provider API Access
|
|
89
|
+
|
|
90
|
+
**Decision:** Workspace/organization-scoped API keys instead of personal keys
|
|
91
|
+
|
|
92
|
+
**Mechanism:**
|
|
93
|
+
- Create a workspace or organization scope with the provider
|
|
94
|
+
- Generate an API key within that scope
|
|
95
|
+
- Store the key as an environment variable (e.g. in a `.env` file)
|
|
96
|
+
- Reference it in config via a secret-reference rather than embedding the value
|
|
97
|
+
|
|
98
|
+
**Why Scoped Keys Over Personal Keys:**
|
|
99
|
+
|
|
100
|
+
1. **Organizational Boundary**
|
|
101
|
+
- Personal keys are tied to an individual account; scoped keys are tied to a business entity
|
|
102
|
+
- Supports multiple team members with separate accounts sharing workspace keys
|
|
103
|
+
- Billing and usage analytics are separated by workspace (clean separation for accounting)
|
|
104
|
+
|
|
105
|
+
2. **Credential Lifecycle Management**
|
|
106
|
+
- If an individual's personal account changes, workspace keys remain stable
|
|
107
|
+
- Key rotation doesn't require changing personal account credentials
|
|
108
|
+
- Ownership can be transferred to the business entity if needed
|
|
109
|
+
|
|
110
|
+
3. **Usage Visibility**
|
|
111
|
+
- The workspace dashboard shows per-agent usage when multiple agents are configured
|
|
112
|
+
- Business usage is isolated from personal experimentation
|
|
113
|
+
|
|
114
|
+
**Trade-offs:**
|
|
115
|
+
- Scoped keys may require a paid plan tier; personal keys may be available on a free tier
|
|
116
|
+
- Additional setup step (create workspace, configure workspace key)
|
|
117
|
+
- **Chosen:** Organizational clarity and multi-agent scaling are worth the cost
|
|
118
|
+
|
|
119
|
+
**Implementation Notes:**
|
|
120
|
+
- Store the API key in a `.env` file (not committed to Git), with `600` permissions
|
|
121
|
+
- The secret-reference pattern means config files can be committed without exposing the key
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### Gateway / Control-Plane Token
|
|
126
|
+
|
|
127
|
+
**Decision:** Token auth via secret reference
|
|
128
|
+
|
|
129
|
+
**Mechanism:**
|
|
130
|
+
- Generate a random high-entropy token during installation
|
|
131
|
+
- Store it as an environment variable (e.g. in a `.env` file or a secret manager)
|
|
132
|
+
- Reference it from config rather than embedding the literal value
|
|
133
|
+
- Require it in the HTTP header: `Authorization: Bearer <token>`
|
|
134
|
+
|
|
135
|
+
**Why Token Auth:**
|
|
136
|
+
|
|
137
|
+
1. **Stateless Authentication**
|
|
138
|
+
- No session management required; the gateway validates the token per request
|
|
139
|
+
- Supports multiple clients (CLI, web UI, agent nodes) with the same token
|
|
140
|
+
- No database or persistent storage needed for auth state
|
|
141
|
+
|
|
142
|
+
2. **Secret-Reference Benefits**
|
|
143
|
+
- The token never appears in the committed config file
|
|
144
|
+
- The token file (`.env`) has explicit `600` permissions
|
|
145
|
+
- Rotation requires updating the secret store only, not the config file
|
|
146
|
+
|
|
147
|
+
3. **Defense-in-Depth with Network Isolation**
|
|
148
|
+
- The gateway binds to loopback only; the token is a second layer of defense
|
|
149
|
+
- Even if the token leaks, an attacker still needs local/tunnel access to reach the gateway
|
|
150
|
+
- An encrypted tunnel/VPN provides transport security so the token isn't exposed in plaintext over the network
|
|
151
|
+
|
|
152
|
+
**Rejected Alternatives:**
|
|
153
|
+
- **Password auth:** Requires hashing, salting, and storage; more complex for a single-user setup
|
|
154
|
+
- **No auth:** Unacceptable even with a loopback bind (a local process compromise could reach the gateway)
|
|
155
|
+
- **Plaintext token in config:** Token visible in the config file; secret reference is strictly better
|
|
156
|
+
|
|
157
|
+
**Implementation Notes:**
|
|
158
|
+
- Generate the token with a cryptographically secure source (e.g. `openssl rand -hex 32`)
|
|
159
|
+
- Rotation: generate a new token, update the secret store, restart the gateway (no config change needed)
|
|
160
|
+
- Treat the token as shown-once; regenerate it if lost
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### Network ACLs (Future Hardening)
|
|
165
|
+
|
|
166
|
+
**Current State:** Default tunnel/VPN ACLs (all nodes can reach all nodes)
|
|
167
|
+
|
|
168
|
+
**Future Hardening:**
|
|
169
|
+
- Restrict the gateway to accept connections only from specific, expected nodes
|
|
170
|
+
- Use access tags for role-based access (e.g. a gateway tag vs. an agent-node tag)
|
|
171
|
+
- Block all other devices from reaching the gateway
|
|
172
|
+
|
|
173
|
+
**Implementation Date:** When a second agent node is added
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Secret-Reference Pattern Standard
|
|
178
|
+
|
|
179
|
+
Use this consistently across all credential storage:
|
|
180
|
+
|
|
181
|
+
```toml
|
|
182
|
+
# In config (safe to commit) — reference the secret, don't inline it
|
|
183
|
+
[some_service]
|
|
184
|
+
auth = { provider = "token", token = { source = "env", id = "SECRET_NAME" } }
|
|
185
|
+
|
|
186
|
+
# In .env (never committed)
|
|
187
|
+
SECRET_NAME=actual-secret-value-here
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Benefits:**
|
|
191
|
+
- Config files are version-controlled without exposing secrets
|
|
192
|
+
- Secrets are rotated by editing the secret store only (no config changes)
|
|
193
|
+
- The secret file has strict `600` permissions
|
|
194
|
+
- Single source of truth for secret values (not duplicated across config files)
|
|
195
|
+
|
|
196
|
+
**Common Source Types:**
|
|
197
|
+
- `env` — Environment variable from a `.env` file or service unit environment
|
|
198
|
+
- `file` — Read from an arbitrary file path (e.g. integration with system keychains)
|
|
199
|
+
- `exec` — Execute a command to retrieve the secret (e.g. integration with vault systems)
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Credential Audit Checklist
|
|
204
|
+
|
|
205
|
+
Regular review (quarterly):
|
|
206
|
+
|
|
207
|
+
- [ ] List all active SSH keys on the Git host; revoke unused keys
|
|
208
|
+
- [ ] List all active model-provider API keys; revoke unused keys
|
|
209
|
+
- [ ] Verify `.env` file permissions are `600` on all machines
|
|
210
|
+
- [ ] Review network ACLs against the current node topology
|
|
211
|
+
- [ ] Check `~/.ssh/` permissions (directory `700`, private keys `600`)
|
|
212
|
+
- [ ] Grep the codebase for hardcoded secrets (should find zero matches)
|
|
213
|
+
- [ ] Review the security audit log for any anomalous credential operations
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## References
|
|
218
|
+
|
|
219
|
+
- [Threat Model](threat-model.md) — Attack surfaces and mitigations
|
|
220
|
+
- [Hardening Checklist](hardening-checklist.md) — Operational security measures
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CI/CD Standards
|
|
3
|
+
audience: both
|
|
4
|
+
last_updated: YYYY-MM-DD
|
|
5
|
+
status: active
|
|
6
|
+
tags: [cicd, pipelines, devops, prospero, azure-devops]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# CI/CD Standards
|
|
10
|
+
|
|
11
|
+
Pipeline patterns, branch policies, and deployment gates for all your projects. Owned by Prospero (DevOps Engineer).
|
|
12
|
+
|
|
13
|
+
## Executive Summary
|
|
14
|
+
|
|
15
|
+
- Every code repository must have a CI pipeline that runs on PR creation and merge to main.
|
|
16
|
+
- Branch policies enforce PR requirements: build must pass, reviewer required, work item linked.
|
|
17
|
+
- Terraform changes use plan-on-PR / apply-on-merge with manual approval gates.
|
|
18
|
+
- Prospero owns pipeline creation and maintenance across all repos.
|
|
19
|
+
- ADR-049 (Spell Loop) and ADR-051 (Prospero) provide the decision rationale.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Pipeline Matrix
|
|
24
|
+
|
|
25
|
+
| Repo | Org | Pipeline | Triggers | Steps | Owner |
|
|
26
|
+
|------|-----|----------|----------|-------|-------|
|
|
27
|
+
| example-app / .NET backend | {ado-org} | Build + Test + Deploy | PR, merge to main | restore → build → test → deploy staging | Prospero |
|
|
28
|
+
| example-app / Mobile | {ado-org} | Build + Test | PR, merge to main | build → unit tests → integration tests → artifact publish | Prospero |
|
|
29
|
+
| example-app / Firmware | {ado-org} | Build + Test | PR, merge to main | PlatformIO build → unit tests → OTA artifact publish | Prospero |
|
|
30
|
+
| ops-docs / docs | {ado-org} | Lint + Link Check | PR | markdownlint → link validation → frontmatter schema check | Prospero |
|
|
31
|
+
| storefront / web | {ado-org} | Build + Deploy | PR, merge to main | build → deploy (platform-dependent) | Prospero |
|
|
32
|
+
| legacy-app / App | {ado-org} | Build + Test | PR, merge to main | dotnet restore → build → test | Prospero |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Branch Policies (Azure DevOps)
|
|
37
|
+
|
|
38
|
+
Applied to all code repositories (not docs-only repos per ADR-048):
|
|
39
|
+
|
|
40
|
+
| Policy | Setting | Rationale |
|
|
41
|
+
|--------|---------|-----------|
|
|
42
|
+
| **Require PR** | All branches → main | No direct pushes to main |
|
|
43
|
+
| **Minimum reviewers** | 1 (Lince for code, Merlin for architecture) | Quality gate |
|
|
44
|
+
| **Build validation** | CI pipeline must pass | No merging broken code |
|
|
45
|
+
| **Work item linking** | Required (when ticketing active) | Traceability |
|
|
46
|
+
| **Comment resolution** | All comments must be resolved | No ignored feedback |
|
|
47
|
+
| **Merge type** | Squash merge or rebase (no merge commits) | Clean linear history |
|
|
48
|
+
|
|
49
|
+
For docs-only repos (Arcane):
|
|
50
|
+
- PR not required (ADR-048 allows local ff-only merge for docs)
|
|
51
|
+
- CI lint check runs on push to any branch
|
|
52
|
+
- Branch discipline still applies (branch → work → ff-only merge)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Pipeline Templates
|
|
57
|
+
|
|
58
|
+
### .NET Backend Pipeline
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
# azure-pipelines.yml
|
|
62
|
+
trigger:
|
|
63
|
+
branches:
|
|
64
|
+
include:
|
|
65
|
+
- main
|
|
66
|
+
paths:
|
|
67
|
+
include:
|
|
68
|
+
- src/**
|
|
69
|
+
|
|
70
|
+
pr:
|
|
71
|
+
branches:
|
|
72
|
+
include:
|
|
73
|
+
- main
|
|
74
|
+
|
|
75
|
+
pool:
|
|
76
|
+
vmImage: 'ubuntu-latest'
|
|
77
|
+
|
|
78
|
+
steps:
|
|
79
|
+
- task: UseDotNet@2
|
|
80
|
+
inputs:
|
|
81
|
+
version: '10.x'
|
|
82
|
+
|
|
83
|
+
- script: dotnet restore
|
|
84
|
+
displayName: 'Restore packages'
|
|
85
|
+
|
|
86
|
+
- script: dotnet build --no-restore --configuration Release
|
|
87
|
+
displayName: 'Build'
|
|
88
|
+
|
|
89
|
+
- script: dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --results-directory $(Agent.TempDirectory)
|
|
90
|
+
displayName: 'Run tests'
|
|
91
|
+
|
|
92
|
+
- task: PublishCodeCoverageResults@2
|
|
93
|
+
inputs:
|
|
94
|
+
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
|
|
95
|
+
failIfCoverageEmpty: true
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Node.js Pipeline
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
trigger:
|
|
102
|
+
branches:
|
|
103
|
+
include:
|
|
104
|
+
- main
|
|
105
|
+
|
|
106
|
+
pr:
|
|
107
|
+
branches:
|
|
108
|
+
include:
|
|
109
|
+
- main
|
|
110
|
+
|
|
111
|
+
pool:
|
|
112
|
+
vmImage: 'ubuntu-latest'
|
|
113
|
+
|
|
114
|
+
steps:
|
|
115
|
+
- task: UseNode@1
|
|
116
|
+
inputs:
|
|
117
|
+
version: '20.x'
|
|
118
|
+
|
|
119
|
+
- script: npm ci
|
|
120
|
+
displayName: 'Install dependencies'
|
|
121
|
+
|
|
122
|
+
- script: npm test
|
|
123
|
+
displayName: 'Run tests'
|
|
124
|
+
|
|
125
|
+
- script: npm run lint
|
|
126
|
+
displayName: 'Lint'
|
|
127
|
+
condition: succeededOrFailed()
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Terraform Pipeline
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
trigger: none # Manual only for apply
|
|
134
|
+
|
|
135
|
+
pr:
|
|
136
|
+
branches:
|
|
137
|
+
include:
|
|
138
|
+
- main
|
|
139
|
+
paths:
|
|
140
|
+
include:
|
|
141
|
+
- infrastructure/terraform/**
|
|
142
|
+
|
|
143
|
+
pool:
|
|
144
|
+
vmImage: 'ubuntu-latest'
|
|
145
|
+
|
|
146
|
+
steps:
|
|
147
|
+
- script: |
|
|
148
|
+
terraform init
|
|
149
|
+
terraform validate
|
|
150
|
+
displayName: 'Validate'
|
|
151
|
+
|
|
152
|
+
- script: terraform plan -out=tfplan
|
|
153
|
+
displayName: 'Plan'
|
|
154
|
+
|
|
155
|
+
- script: checkov -d . --framework terraform
|
|
156
|
+
displayName: 'Security scan (Checkov)'
|
|
157
|
+
|
|
158
|
+
# Apply step is manual — requires approval gate
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Markdown Lint Pipeline
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
trigger:
|
|
165
|
+
branches:
|
|
166
|
+
include:
|
|
167
|
+
- '**'
|
|
168
|
+
paths:
|
|
169
|
+
include:
|
|
170
|
+
- '**.md'
|
|
171
|
+
|
|
172
|
+
pool:
|
|
173
|
+
vmImage: 'ubuntu-latest'
|
|
174
|
+
|
|
175
|
+
steps:
|
|
176
|
+
- task: UseNode@1
|
|
177
|
+
inputs:
|
|
178
|
+
version: '20.x'
|
|
179
|
+
|
|
180
|
+
- script: npx markdownlint-cli2 "**/*.md" "#node_modules"
|
|
181
|
+
displayName: 'Lint markdown'
|
|
182
|
+
|
|
183
|
+
- script: npx markdown-link-check --config .markdown-link-check.json **/*.md
|
|
184
|
+
displayName: 'Check links'
|
|
185
|
+
condition: succeededOrFailed()
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Deployment Gates
|
|
191
|
+
|
|
192
|
+
| Environment | Gate | Who Approves |
|
|
193
|
+
|-------------|------|-------------|
|
|
194
|
+
| **Staging** | CI passes + PR approved | Automatic on merge |
|
|
195
|
+
| **Production** | Staging verified + manual approval | Human (operator) |
|
|
196
|
+
| **Terraform apply** | Plan reviewed + Checkov clean | Human (operator) |
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Prospero's Responsibilities
|
|
201
|
+
|
|
202
|
+
1. **Create and maintain all CI/CD pipelines** across Azure DevOps organizations
|
|
203
|
+
2. **Configure branch policies** per repo risk level
|
|
204
|
+
3. **Monitor pipeline health** — alert on persistent failures
|
|
205
|
+
4. **Manage Terraform state** — ensure remote state backend is configured
|
|
206
|
+
5. **Set up Azure cost alerts** — per resource group, per business
|
|
207
|
+
6. **Security scanning** — Checkov for Terraform, dependency audits for code repos
|
|
208
|
+
7. **Deployment automation** — Azure Functions, App Service, container deployments
|
|
209
|
+
8. **Documentation** — keep this file and pipeline configs in sync
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Implementation Priority
|
|
214
|
+
|
|
215
|
+
1. WidgetApp .NET backend pipeline (highest business priority)
|
|
216
|
+
2. ops docs lint pipeline (catches documentation drift)
|
|
217
|
+
3. WidgetApp mobile pipeline (when mobile development begins)
|
|
218
|
+
4. WidgetApp firmware pipeline (when firmware work resumes)
|
|
219
|
+
5. Terraform pipeline (when new Azure resources are provisioned)
|
|
220
|
+
6. AcmeStore pipeline (when platform is selected)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
## Related
|
|
224
|
+
|
|
225
|
+
- [[DECISIONS]]
|
|
226
|
+
- [[governance/development-methodology|Development Methodology]]
|
|
227
|
+
- [[governance/testing-standards|Testing Standards]]
|