@kitsy/cnos-docs 1.9.2 → 1.11.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/docs/api/runtime.mdx +16 -0
- package/docs/cli/doctor.mdx +18 -16
- package/docs/cli/spec.mdx +75 -0
- package/docs/guides/go-runtime.mdx +206 -0
- package/docs/guides/secrets.mdx +18 -0
- package/docs/guides/vault-providers.mdx +263 -0
- package/docs/reference/manifest.mdx +20 -0
- package/manifest.yml +6 -0
- package/package.json +1 -1
package/docs/api/runtime.mdx
CHANGED
|
@@ -37,6 +37,8 @@ The runtime currently exposes:
|
|
|
37
37
|
- `cnos.log(message)`
|
|
38
38
|
- `cnos.loadProjection(path)`
|
|
39
39
|
- `cnos.registerRuntimeProvider(namespace, provider)`
|
|
40
|
+
- `cnos.registerSecretVaultProvider(factory)`
|
|
41
|
+
- `cnos.registerSecretVaultProviders(factories)`
|
|
40
42
|
- `cnos.refreshSecrets()`
|
|
41
43
|
- `cnos.refreshSecret(key)`
|
|
42
44
|
|
|
@@ -111,6 +113,20 @@ cnos.registerRuntimeProvider('request', (key) => {
|
|
|
111
113
|
|
|
112
114
|
That lets server-side derived values depend on live request, session, or app-framework context without adding a second config layer.
|
|
113
115
|
|
|
116
|
+
## Secret Vault Providers
|
|
117
|
+
|
|
118
|
+
Vault selection is declared in `.cnos/cnos.yml`; runtime code only declares which provider implementations were compiled into the bundle.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import cnos from '@kitsy/cnos';
|
|
122
|
+
import { createGcpSecretManagerVaultProvider } from '@kitsy/cnos-vault-gcp-secret-manager';
|
|
123
|
+
|
|
124
|
+
cnos.registerSecretVaultProvider(createGcpSecretManagerVaultProvider());
|
|
125
|
+
await cnos.ready();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Provider packages and batteries-included wrappers should register capabilities before `ready()`. CNOS does not dynamically load provider packages from manifest config.
|
|
129
|
+
|
|
114
130
|
## Typed values
|
|
115
131
|
|
|
116
132
|
CNOS values are not limited to strings. If the underlying config stores numbers, booleans, arrays, or objects, runtime reads return those values as-is.
|
package/docs/cli/doctor.mdx
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: cnos doctor
|
|
3
|
-
description: Run diagnostics across workspaces, exports, and security rules.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# cnos doctor
|
|
7
|
-
|
|
8
|
-
```bash
|
|
9
|
-
cnos doctor
|
|
10
|
-
cnos doctor --json
|
|
11
|
-
cnos doctor --fix-secret-env-mappings
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
The security diagnostics now flag explicit `secret.*` env mappings as a risk because they enable plaintext secret emission into private env surfaces.
|
|
15
|
-
|
|
16
|
-
If those mappings were added by mistake, `cnos doctor --fix-secret-env-mappings` removes them from `envMapping.explicit` in one shot and then reruns diagnostics.
|
|
1
|
+
---
|
|
2
|
+
title: cnos doctor
|
|
3
|
+
description: Run diagnostics across workspaces, exports, and security rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# cnos doctor
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cnos doctor
|
|
10
|
+
cnos doctor --json
|
|
11
|
+
cnos doctor --fix-secret-env-mappings
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The security diagnostics now flag explicit `secret.*` env mappings as a risk because they enable plaintext secret emission into private env surfaces.
|
|
15
|
+
|
|
16
|
+
If those mappings were added by mistake, `cnos doctor --fix-secret-env-mappings` removes them from `envMapping.explicit` in one shot and then reruns diagnostics.
|
|
17
|
+
|
|
18
|
+
When manifest `schema:` entries exist, `cnos doctor` also points to `cnos spec doctor` for spec-vs-config coverage and guided remediation.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: cnos spec
|
|
3
|
+
description: Author and inspect CNOS config specs stored under schema.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# cnos spec
|
|
7
|
+
|
|
8
|
+
`cnos spec` manages manifest-global config specification entries stored under `schema:` in `.cnos/cnos.yml`.
|
|
9
|
+
|
|
10
|
+
Use `cnos define`, `cnos value set`, and `cnos secret set` for concrete config values and secret refs.
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
cnos spec list
|
|
16
|
+
cnos spec show value.server.port
|
|
17
|
+
cnos spec set value.server.port --type number --required --summary "HTTP server port"
|
|
18
|
+
cnos spec delete value.legacy.flag
|
|
19
|
+
cnos spec doctor
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## list
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cnos spec list
|
|
26
|
+
cnos spec list --prefix value.server.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## show
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cnos spec show value.server.port
|
|
33
|
+
cnos spec show value.server.port --json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## set
|
|
37
|
+
|
|
38
|
+
`cnos spec set` supports two modes:
|
|
39
|
+
|
|
40
|
+
- Non-interactive: pass one or more field flags.
|
|
41
|
+
- Interactive: no field flags in a TTY.
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cnos spec set value.server.port --type number --required --summary "HTTP server port"
|
|
47
|
+
cnos spec set value.app.stage --enum '["local","stage","prod"]'
|
|
48
|
+
cnos spec set value.legacy.flag --clear-deprecated
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Field flags use JSON-first parsing for `--default`, `--example`, and `--enum`.
|
|
52
|
+
|
|
53
|
+
For `secret.*` keys, `--default`, `--example`, and `--enum` are rejected to avoid plaintext secret material in the manifest.
|
|
54
|
+
|
|
55
|
+
## delete
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
cnos spec delete value.legacy.flag
|
|
59
|
+
cnos spec remove value.legacy.flag --json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## doctor
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cnos spec doctor
|
|
66
|
+
cnos spec doctor --json
|
|
67
|
+
cnos spec doctor --fill-missing
|
|
68
|
+
cnos spec doctor --review-all
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`--fill-missing` and `--review-all` are interactive write modes. They currently:
|
|
72
|
+
|
|
73
|
+
- require a TTY,
|
|
74
|
+
- require a writable local root (remote roots are read-only),
|
|
75
|
+
- reject `--json`.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Go Runtime
|
|
3
|
+
description: Use CNOS directly from Go services through projections, native .cnos resolution, and Git-backed remote roots.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Go Runtime
|
|
7
|
+
|
|
8
|
+
CNOS now ships a first-party Go runtime client in [`packages/go`](https://github.com/kitsyai/cnos/tree/main/packages/go).
|
|
9
|
+
|
|
10
|
+
The Go client reads the same runtime bootstrap contracts that the Node runtime already understands:
|
|
11
|
+
|
|
12
|
+
- `__CNOS_GRAPH__`
|
|
13
|
+
- `__CNOS_PROJECTION__`
|
|
14
|
+
- explicit `.cnos-server.json`
|
|
15
|
+
- autodiscovered `.cnos-server.json` next to `.cnosrc.yml`
|
|
16
|
+
|
|
17
|
+
That means a Go service can consume CNOS values and secrets directly without dropping back to `cnos build env -> .env`.
|
|
18
|
+
|
|
19
|
+
When no projection is present, the Go runtime now falls back to native authoring-time resolution from `.cnos/` or `cnos/`. That path understands:
|
|
20
|
+
|
|
21
|
+
- `.cnosrc.yml` anchor discovery
|
|
22
|
+
- `git+https://...#ref` and `git+ssh://...#ref` remote roots
|
|
23
|
+
- `.cnos-workspace.yml`
|
|
24
|
+
- workspace inheritance and optional global roots
|
|
25
|
+
- profile activation and inheritance
|
|
26
|
+
- filesystem values and secrets
|
|
27
|
+
- dotenv layers
|
|
28
|
+
- process env mappings
|
|
29
|
+
- public promotion
|
|
30
|
+
- runtime-derived values
|
|
31
|
+
- manifest vault mappings for environment and local vault secrets
|
|
32
|
+
|
|
33
|
+
## Build the projection
|
|
34
|
+
|
|
35
|
+
For deployment or local packaging:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cnos build server --profile prod --to .cnos-server.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For process bootstrap during development:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
cnos run -- ./your-go-service
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Import the runtime
|
|
48
|
+
|
|
49
|
+
Current module path:
|
|
50
|
+
|
|
51
|
+
```go
|
|
52
|
+
import cnos "github.com/kitsyai/cnos/packages/go"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then load the runtime:
|
|
56
|
+
|
|
57
|
+
```go
|
|
58
|
+
runtime, err := cnos.Load(cnos.Options{})
|
|
59
|
+
if err != nil {
|
|
60
|
+
panic(err)
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or use the package-level singleton for the closest Node-style runtime flow:
|
|
65
|
+
|
|
66
|
+
```go
|
|
67
|
+
if err := cnos.Ready(); err != nil {
|
|
68
|
+
panic(err)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
value, ok, err := cnos.Read("value.app.version")
|
|
72
|
+
if err != nil {
|
|
73
|
+
panic(err)
|
|
74
|
+
}
|
|
75
|
+
_ = value
|
|
76
|
+
_ = ok
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`Load()` checks sources in this order:
|
|
80
|
+
|
|
81
|
+
1. `ProjectionData` passed through `LoadProjection`
|
|
82
|
+
2. explicit path from `cnos.Options{ProjectionPath: ...}`
|
|
83
|
+
3. `__CNOS_GRAPH__`
|
|
84
|
+
4. `__CNOS_PROJECTION__`
|
|
85
|
+
5. `.cnos-server.json` in the current working directory
|
|
86
|
+
6. `.cnos-server.json` beside a discovered `.cnosrc.yml`
|
|
87
|
+
7. native authoring-time resolution from `cnos.Options{Root: ...}` or a discovered `.cnosrc.yml`
|
|
88
|
+
|
|
89
|
+
If the process already has `__CNOS_GRAPH__`, `__CNOS_PROJECTION__`, or a nearby `.cnos-server.json`, the package singleton bootstraps automatically and `Ready()` is optional.
|
|
90
|
+
|
|
91
|
+
## Read values and secrets
|
|
92
|
+
|
|
93
|
+
```go
|
|
94
|
+
port, _, err := runtime.Value("server.port")
|
|
95
|
+
if err != nil {
|
|
96
|
+
panic(err)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
token, _, err := runtime.Secret("app.token")
|
|
100
|
+
if err != nil {
|
|
101
|
+
panic(err)
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The Go runtime reconstructs the same logical keys used in CNOS:
|
|
106
|
+
|
|
107
|
+
- `value.*`
|
|
108
|
+
- `secret.*`
|
|
109
|
+
- `public.*`
|
|
110
|
+
- `meta.profile`
|
|
111
|
+
- `meta.workspace`
|
|
112
|
+
- `meta.cnos_version`
|
|
113
|
+
|
|
114
|
+
Inspect/provenance is also available directly in Go:
|
|
115
|
+
|
|
116
|
+
```go
|
|
117
|
+
inspect, err := runtime.Inspect("value.app.version")
|
|
118
|
+
if err != nil {
|
|
119
|
+
panic(err)
|
|
120
|
+
}
|
|
121
|
+
_ = inspect
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Derived values stay live
|
|
125
|
+
|
|
126
|
+
Runtime-dependent derived formulas in the server projection are evaluated at read time, not frozen during build.
|
|
127
|
+
|
|
128
|
+
Example CNOS config:
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
app:
|
|
132
|
+
origin:
|
|
133
|
+
$derive: "https://${value.app.host}:${process.env.PORT}"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
In Go:
|
|
137
|
+
|
|
138
|
+
```go
|
|
139
|
+
origin, _, err := runtime.Value("app.origin")
|
|
140
|
+
if err != nil {
|
|
141
|
+
panic(err)
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
If `PORT` changes in the host process, the next read re-evaluates the formula.
|
|
146
|
+
|
|
147
|
+
## Custom runtime namespaces
|
|
148
|
+
|
|
149
|
+
Custom server-only runtime namespaces work the same way as in Node. Register a provider for any namespace that was declared in the CNOS manifest and carried into the server projection.
|
|
150
|
+
|
|
151
|
+
```go
|
|
152
|
+
host := ""
|
|
153
|
+
|
|
154
|
+
if err := runtime.RegisterRuntimeProvider("request", func(path string) any {
|
|
155
|
+
if path == "headers.host" && host != "" {
|
|
156
|
+
return host
|
|
157
|
+
}
|
|
158
|
+
return nil
|
|
159
|
+
}); err != nil {
|
|
160
|
+
panic(err)
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The built-in `process.*` namespace covers `env.*`, `cwd`, `platform`, `arch`, and `pid`. `process.node.version` is still Node-only.
|
|
165
|
+
|
|
166
|
+
## Secret hydration
|
|
167
|
+
|
|
168
|
+
The Go runtime supports built-in secret-ref providers used by server projections:
|
|
169
|
+
|
|
170
|
+
- `environment`
|
|
171
|
+
- `github-secrets`
|
|
172
|
+
- `local`
|
|
173
|
+
|
|
174
|
+
Remote providers such as GCP Secret Manager, AWS Secrets Manager, HashiCorp Vault, and Azure Key Vault are compiled into the Go binary by registering provider factories:
|
|
175
|
+
|
|
176
|
+
```go
|
|
177
|
+
runtime, err := cnos.Load(cnos.Options{
|
|
178
|
+
SecretVaultProviders: []cnos.SecretVaultProviderFactory{gcpFactory},
|
|
179
|
+
})
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The manifest remains the configuration source for which named vault uses which provider. Go does not dynamically load provider packages from `.cnos.yml`.
|
|
183
|
+
|
|
184
|
+
For local vaults, the Go client reuses the same CNOS auth conventions:
|
|
185
|
+
|
|
186
|
+
- `__CNOS_VAULT_KEY_<VAULT>__`
|
|
187
|
+
- `~/.cnos/secrets/sessions/<vault>.json`
|
|
188
|
+
- `keychain:cnos/<vault>`
|
|
189
|
+
- `CNOS_SECRET_PASSPHRASE_<VAULT>`
|
|
190
|
+
- `CNOS_SECRET_PASSPHRASE`
|
|
191
|
+
|
|
192
|
+
It also understands the encrypted secret payload generated by:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
cnos run --auth -- ./your-go-service
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
That lets a Go process start with already-resolved secret values even when it is not re-authenticating to the local vault itself.
|
|
199
|
+
|
|
200
|
+
## Current limits
|
|
201
|
+
|
|
202
|
+
The remaining Go-specific gaps are:
|
|
203
|
+
|
|
204
|
+
- browser/public runtime behavior
|
|
205
|
+
|
|
206
|
+
Use it as the server-runtime companion to `cnos build server`, `cnos run`, local `.cnos/` authoring flows, and Git-backed shared config repos.
|
package/docs/guides/secrets.mdx
CHANGED
|
@@ -46,3 +46,21 @@ By default:
|
|
|
46
46
|
- repo files store only refs
|
|
47
47
|
- local secret material stays outside the repo
|
|
48
48
|
- reads are masked unless `--reveal` is explicitly requested
|
|
49
|
+
|
|
50
|
+
Remote provider packages are compiled into the runtime and selected through `vaults.<name>.provider` in the manifest. CNOS does not dynamically load provider packages from config.
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
vaults:
|
|
54
|
+
prod-gcp:
|
|
55
|
+
provider: gcp-secret-manager
|
|
56
|
+
auth:
|
|
57
|
+
method: iam
|
|
58
|
+
config:
|
|
59
|
+
projectId: acme-prod
|
|
60
|
+
fallback:
|
|
61
|
+
- provider: environment
|
|
62
|
+
mapping:
|
|
63
|
+
DB_PASSWORD: db.password
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
See [Vault Providers](/guides/vault-providers) for the provider package contract, conformance testkit, and security rules.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Vault Provider Packages
|
|
3
|
+
description: Build and test compiled-in CNOS secret vault providers.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vault Provider Packages
|
|
7
|
+
|
|
8
|
+
Remote vault providers are compiled into the application runtime. CNOS never loads provider packages dynamically from `.cnos/cnos.yml`.
|
|
9
|
+
|
|
10
|
+
## Package names
|
|
11
|
+
|
|
12
|
+
Official providers use this package shape:
|
|
13
|
+
|
|
14
|
+
- `@kitsy/cnos-vault-gcp-secret-manager`
|
|
15
|
+
- `@kitsy/cnos-vault-aws-secrets-manager`
|
|
16
|
+
- `@kitsy/cnos-vault-hashicorp`
|
|
17
|
+
- `@kitsy/cnos-vault-azure-key-vault`
|
|
18
|
+
- `@kitsy/cnos-vault-firebase-secrets`
|
|
19
|
+
|
|
20
|
+
Each package must export a factory named `create<Vendor>VaultProvider()`. The factory returns a `SecretVaultProviderFactory` whose `provider` field exactly matches the manifest provider name.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import cnos from '@kitsy/cnos';
|
|
24
|
+
import { createGcpSecretManagerVaultProvider } from '@kitsy/cnos-vault-gcp-secret-manager';
|
|
25
|
+
|
|
26
|
+
cnos.registerSecretVaultProvider(createGcpSecretManagerVaultProvider());
|
|
27
|
+
await cnos.ready();
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Manifest contract
|
|
31
|
+
|
|
32
|
+
Provider selection belongs in config:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
vaults:
|
|
36
|
+
prod-gcp:
|
|
37
|
+
provider: gcp-secret-manager
|
|
38
|
+
auth:
|
|
39
|
+
method: iam
|
|
40
|
+
config:
|
|
41
|
+
projectId: acme-prod
|
|
42
|
+
fallback:
|
|
43
|
+
- provider: environment
|
|
44
|
+
mapping:
|
|
45
|
+
DB_PASSWORD: db.password
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Secret refs should normally inherit from the named vault:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
db:
|
|
52
|
+
password:
|
|
53
|
+
vault: prod-gcp
|
|
54
|
+
ref: db.password
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Do not set a different `provider` on a ref that also names a vault. CNOS rejects provider/vault mismatches so Node, Go, and projections all agree.
|
|
58
|
+
|
|
59
|
+
## Runtime contract
|
|
60
|
+
|
|
61
|
+
Every provider must implement the `SecretVaultProvider` interface:
|
|
62
|
+
|
|
63
|
+
- `authenticate(authConfig)` resolves credentials supplied by CNOS.
|
|
64
|
+
- `batchGet(refs)` is the startup and refresh path.
|
|
65
|
+
- `get(ref)` exists for compatibility and narrow single-ref use, but provider tests must prove startup and `refreshSecrets()` do not call it.
|
|
66
|
+
- `set(ref, value)` and `delete(ref)` may be writable or may reject. Declare the expected capability in testkit setup.
|
|
67
|
+
- `list()` returns known refs when the backing platform supports listing.
|
|
68
|
+
- `healthCheck()` is optional for remote providers.
|
|
69
|
+
|
|
70
|
+
Startup hydration and full refresh are batch-only. Individual application reads use the CNOS in-memory cache and must not perform remote I/O.
|
|
71
|
+
|
|
72
|
+
## Auth and projection safety
|
|
73
|
+
|
|
74
|
+
Provider auth should prefer platform identity:
|
|
75
|
+
|
|
76
|
+
- GCP: Application Default Credentials or attached service account.
|
|
77
|
+
- AWS: IAM role or standard AWS credential chain.
|
|
78
|
+
- Azure: managed identity or default credential chain.
|
|
79
|
+
- HashiCorp Vault: token sources such as `env:`, `file:`, or keychain.
|
|
80
|
+
- Firebase: direct provider support plus explicit `environment` fallback for injected secrets.
|
|
81
|
+
|
|
82
|
+
Server projections may include safe metadata such as `projectId`, `region`, `endpoint`, `address`, `namespace`, or `tenant`. They must not include raw secrets, private keys, bearer tokens, credential blobs, or client secrets. CNOS sanitizes projected `auth.config`, but provider authors should design manifest config so credential material is referenced by source (`env:NAME`, `file:PATH`, `keychain:NAME`) rather than stored inline.
|
|
83
|
+
|
|
84
|
+
## Conformance tests
|
|
85
|
+
|
|
86
|
+
Provider packages should use `@kitsy/cnos-vault-testkit`:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import {
|
|
90
|
+
defineSecretVaultProviderConformanceSuite,
|
|
91
|
+
defineSecretVaultRuntimeConformanceSuite,
|
|
92
|
+
} from '@kitsy/cnos-vault-testkit';
|
|
93
|
+
|
|
94
|
+
defineSecretVaultProviderConformanceSuite('gcp-secret-manager', () => ({
|
|
95
|
+
factory: createGcpSecretManagerVaultProvider(),
|
|
96
|
+
definition,
|
|
97
|
+
auth,
|
|
98
|
+
refs,
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
defineSecretVaultRuntimeConformanceSuite('gcp-secret-manager', () => ({
|
|
102
|
+
factory: createGcpSecretManagerVaultProvider(),
|
|
103
|
+
vaultId: 'prod-gcp',
|
|
104
|
+
definition,
|
|
105
|
+
refs,
|
|
106
|
+
processEnv,
|
|
107
|
+
}));
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The shared suite verifies provider auth, batch reads, missing refs, runtime startup hydration, projection bootstrap, refresh batching, safe projection metadata, and explicit environment fallback behavior.
|
|
111
|
+
|
|
112
|
+
## Google Secret Manager
|
|
113
|
+
|
|
114
|
+
Install and register the compiled-in provider:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import cnos from '@kitsy/cnos';
|
|
118
|
+
import { createGcpSecretManagerVaultProvider } from '@kitsy/cnos-vault-gcp-secret-manager';
|
|
119
|
+
|
|
120
|
+
cnos.registerSecretVaultProvider(createGcpSecretManagerVaultProvider());
|
|
121
|
+
await cnos.ready();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use `auth.method: iam` and let the official Google SDK resolve Application Default Credentials or an attached service account:
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
vaults:
|
|
128
|
+
prod-gcp:
|
|
129
|
+
provider: gcp-secret-manager
|
|
130
|
+
auth:
|
|
131
|
+
method: iam
|
|
132
|
+
config:
|
|
133
|
+
projectId: acme-prod
|
|
134
|
+
mapping:
|
|
135
|
+
db-password: db.password
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
CNOS resolves `secret.db.password` from `projects/acme-prod/secrets/db-password/versions/latest`. Set `auth.config.version` to read a pinned version, or `auth.config.location` for regional Secret Manager resources. A full ref such as `projects/acme-prod/secrets/db-password/versions/5` is also accepted.
|
|
139
|
+
|
|
140
|
+
## Firebase Secrets
|
|
141
|
+
|
|
142
|
+
Install and register the compiled-in provider:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import cnos from '@kitsy/cnos';
|
|
146
|
+
import { createFirebaseSecretsVaultProvider } from '@kitsy/cnos-vault-firebase-secrets';
|
|
147
|
+
|
|
148
|
+
cnos.registerSecretVaultProvider(createFirebaseSecretsVaultProvider());
|
|
149
|
+
await cnos.ready();
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Firebase Secrets are backed by Google Secret Manager. Use `auth.method: iam` and let the official Google SDK resolve Application Default Credentials or an attached service account:
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
vaults:
|
|
156
|
+
prod-firebase:
|
|
157
|
+
provider: firebase-secrets
|
|
158
|
+
auth:
|
|
159
|
+
method: iam
|
|
160
|
+
config:
|
|
161
|
+
projectId: acme-prod
|
|
162
|
+
mapping:
|
|
163
|
+
DB_PASSWORD: db.password
|
|
164
|
+
fallback:
|
|
165
|
+
- provider: environment
|
|
166
|
+
mapping:
|
|
167
|
+
DB_PASSWORD: db.password
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
CNOS resolves `secret.db.password` from `projects/acme-prod/secrets/DB_PASSWORD/versions/latest`. Set `auth.config.version` to read a pinned version, or `auth.config.location` for regional Secret Manager resources. A full ref such as `projects/acme-prod/secrets/DB_PASSWORD/versions/5` is also accepted.
|
|
171
|
+
|
|
172
|
+
Firebase and Google Cloud Functions can inject secrets as environment variables. Model that as an explicit `environment` fallback in the vault definition; CNOS never silently falls back to env when a remote provider fails.
|
|
173
|
+
|
|
174
|
+
## AWS Secrets Manager
|
|
175
|
+
|
|
176
|
+
Install and register the compiled-in provider:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import cnos from '@kitsy/cnos';
|
|
180
|
+
import { createAwsSecretsManagerVaultProvider } from '@kitsy/cnos-vault-aws-secrets-manager';
|
|
181
|
+
|
|
182
|
+
cnos.registerSecretVaultProvider(createAwsSecretsManagerVaultProvider());
|
|
183
|
+
await cnos.ready();
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Use `auth.method: iam` and let AWS SDK v3 resolve credentials from IAM roles, web identity, environment credentials, or the standard AWS provider chain:
|
|
187
|
+
|
|
188
|
+
```yaml
|
|
189
|
+
vaults:
|
|
190
|
+
prod-aws:
|
|
191
|
+
provider: aws-secrets-manager
|
|
192
|
+
auth:
|
|
193
|
+
method: iam
|
|
194
|
+
config:
|
|
195
|
+
region: us-east-1
|
|
196
|
+
mapping:
|
|
197
|
+
db/password: db.password
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
CNOS resolves `secret.db.password` from the AWS secret ID `db/password`. Set `auth.config.versionId` or `auth.config.versionStage` for pinned or staged reads. Secret refs may also be direct AWS secret names or ARNs when no mapping is required.
|
|
201
|
+
|
|
202
|
+
## HashiCorp Vault
|
|
203
|
+
|
|
204
|
+
Install and register the compiled-in provider:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import cnos from '@kitsy/cnos';
|
|
208
|
+
import { createHashicorpVaultProvider } from '@kitsy/cnos-vault-hashicorp';
|
|
209
|
+
|
|
210
|
+
cnos.registerSecretVaultProvider(createHashicorpVaultProvider());
|
|
211
|
+
await cnos.ready();
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Use `auth.method: token` and source the Vault token from env, file, or keychain. CNOS resolves the token and passes it to Vault as `X-Vault-Token`:
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
vaults:
|
|
218
|
+
prod-vault:
|
|
219
|
+
provider: hashicorp-vault
|
|
220
|
+
auth:
|
|
221
|
+
method: token
|
|
222
|
+
token:
|
|
223
|
+
from:
|
|
224
|
+
- env:VAULT_TOKEN
|
|
225
|
+
config:
|
|
226
|
+
address: https://vault.example.com
|
|
227
|
+
mount: secret
|
|
228
|
+
namespace: admin/team-a
|
|
229
|
+
version: 2
|
|
230
|
+
mapping:
|
|
231
|
+
db/password#password: db.password
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
For KV v2, CNOS reads `secret.data.db/password` and extracts the `password` field. Use `path#field` refs or mapping keys to select fields from a Vault secret object. Set `auth.config.version: 1` for KV v1 mounts, and `auth.config.path` to apply a shared path prefix.
|
|
235
|
+
|
|
236
|
+
## Azure Key Vault
|
|
237
|
+
|
|
238
|
+
Install and register the compiled-in provider:
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
import cnos from '@kitsy/cnos';
|
|
242
|
+
import { createAzureKeyVaultProvider } from '@kitsy/cnos-vault-azure-key-vault';
|
|
243
|
+
|
|
244
|
+
cnos.registerSecretVaultProvider(createAzureKeyVaultProvider());
|
|
245
|
+
await cnos.ready();
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Use `auth.method: iam` and let Azure Identity resolve credentials from managed identity, workload identity, environment credentials, or the standard `DefaultAzureCredential` chain:
|
|
249
|
+
|
|
250
|
+
```yaml
|
|
251
|
+
vaults:
|
|
252
|
+
prod-azure:
|
|
253
|
+
provider: azure-key-vault
|
|
254
|
+
auth:
|
|
255
|
+
method: iam
|
|
256
|
+
config:
|
|
257
|
+
vaultUrl: https://acme-prod.vault.azure.net
|
|
258
|
+
tenantId: 00000000-0000-0000-0000-000000000000
|
|
259
|
+
mapping:
|
|
260
|
+
db-password: db.password
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
CNOS resolves `secret.db.password` from the Azure secret name `db-password`. Set `auth.config.version` for a pinned version, or use a full Azure secret URL such as `https://acme-prod.vault.azure.net/secrets/db-password/version-id` as the ref when no mapping is required.
|
|
@@ -18,3 +18,23 @@ Key sections:
|
|
|
18
18
|
- `writePolicy`
|
|
19
19
|
|
|
20
20
|
Use the main repo spec for the exhaustive schema until this reference grows into the full field-by-field version.
|
|
21
|
+
|
|
22
|
+
## Vaults
|
|
23
|
+
|
|
24
|
+
`vaults` declare named secret backends. Secret refs can name a vault and omit `provider`; CNOS resolves the provider from the vault definition.
|
|
25
|
+
|
|
26
|
+
```yaml
|
|
27
|
+
vaults:
|
|
28
|
+
prod-gcp:
|
|
29
|
+
provider: gcp-secret-manager
|
|
30
|
+
auth:
|
|
31
|
+
method: iam
|
|
32
|
+
config:
|
|
33
|
+
projectId: my-prod-project
|
|
34
|
+
fallback:
|
|
35
|
+
- provider: environment
|
|
36
|
+
mapping:
|
|
37
|
+
DB_PASSWORD: db.password
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Fallbacks are explicit and ordered. CNOS never silently falls back to environment variables unless a fallback provider is declared.
|
package/manifest.yml
CHANGED
|
@@ -19,6 +19,8 @@ sidebar:
|
|
|
19
19
|
items:
|
|
20
20
|
- path: guides/backend
|
|
21
21
|
label: Backend Projects
|
|
22
|
+
- path: guides/go-runtime
|
|
23
|
+
label: Go Runtime
|
|
22
24
|
- path: guides/frontend-vite
|
|
23
25
|
label: Frontend with Vite
|
|
24
26
|
- path: guides/frontend-webpack
|
|
@@ -41,6 +43,8 @@ sidebar:
|
|
|
41
43
|
label: Derived Values
|
|
42
44
|
- path: guides/secrets
|
|
43
45
|
label: Secrets and Vaults
|
|
46
|
+
- path: guides/vault-providers
|
|
47
|
+
label: Vault Providers
|
|
44
48
|
- path: guides/migration
|
|
45
49
|
label: Migrating from .env
|
|
46
50
|
- path: guides/generated-env-files
|
|
@@ -67,6 +71,8 @@ sidebar:
|
|
|
67
71
|
label: cnos secret
|
|
68
72
|
- path: cli/define
|
|
69
73
|
label: cnos define
|
|
74
|
+
- path: cli/spec
|
|
75
|
+
label: cnos spec
|
|
70
76
|
- path: cli/list
|
|
71
77
|
label: cnos list
|
|
72
78
|
- path: cli/read
|