@kitsy/cnos-docs 1.6.1 → 1.8.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.
@@ -16,3 +16,32 @@ Only promoted browser-safe values are available here.
16
16
  Framework integrations such as `@kitsy/cnos-vite`, `@kitsy/cnos-next`, and `@kitsy/cnos-webpack` are responsible for embedding that browser payload during the build.
17
17
 
18
18
  The browser runtime does not fetch config over the network. It reads from data already embedded into the bundle/runtime globals by the framework integration, so it follows the same bundle and service-worker caching behavior as the rest of your frontend assets.
19
+
20
+ ## Cross-App Browser Config
21
+
22
+ Use the same runtime for shared browser-safe values such as sibling app origins, CDN roots, public feature flags, or analytics ids.
23
+
24
+ ```yaml
25
+ public:
26
+ promote:
27
+ - value.apps.docs.origin
28
+ - value.apps.console.origin
29
+ ```
30
+
31
+ ```ts
32
+ import cnos from '@kitsy/cnos/browser';
33
+
34
+ const docsOrigin = cnos('public.apps.docs.origin');
35
+ const consoleOrigin = cnos('public.apps.console.origin');
36
+ ```
37
+
38
+ This is intentionally simple:
39
+
40
+ 1. define the values in CNOS
41
+ 2. promote them to `public.*`
42
+ 3. install the framework integration
43
+ 4. read them in browser code with `@kitsy/cnos/browser`
44
+
45
+ You should not need a second app-specific browser config mechanism on top of CNOS.
46
+
47
+ Derived public values are supported too, but only when CNOS can resolve them safely at build time. If a promoted key depends on a server-only runtime namespace such as `process.*` or `request.*`, the browser/public build fails instead of emitting unstable data.
@@ -13,3 +13,57 @@ const runtime = await createCnos({
13
13
  profile: 'stage',
14
14
  });
15
15
  ```
16
+
17
+ Common options:
18
+
19
+ - `cwd`
20
+ - `root`
21
+ - `workspace`
22
+ - `profile`
23
+ - `globalRoot`
24
+ - `cacheMode`
25
+ - `cacheTtlSeconds`
26
+ - `processEnv`
27
+
28
+ `root` can be a local path or a remote git root URI:
29
+
30
+ ```ts
31
+ const runtime = await createCnos({
32
+ root: 'git+https://github.com/org/config.git#v2.1.0',
33
+ workspace: 'travel',
34
+ });
35
+ ```
36
+
37
+ Derived values and runtime namespaces work through the explicit runtime too:
38
+
39
+ ```ts
40
+ import { createCnos } from '@kitsy/cnos/configure';
41
+
42
+ const runtime = await createCnos({
43
+ cwd: process.cwd(),
44
+ profile: 'prod',
45
+ });
46
+
47
+ runtime.registerRuntimeProvider('request', (key) => {
48
+ if (key === 'headers.host') {
49
+ return currentRequest?.headers.host;
50
+ }
51
+
52
+ return undefined;
53
+ });
54
+
55
+ const origin = runtime.value('app.origin');
56
+ ```
57
+
58
+ Workspace selection can come from three places:
59
+
60
+ 1. explicit `workspace` in `createCnos({ ... })`
61
+ 2. a package-local `.cnosrc.yml`
62
+ 3. the manifest default workspace
63
+
64
+ Typical monorepo package anchor:
65
+
66
+ ```yaml
67
+ root: ../../.cnos
68
+ workspace: api
69
+ ```
@@ -36,6 +36,7 @@ The runtime currently exposes:
36
36
  - `cnos.format(message)`
37
37
  - `cnos.log(message)`
38
38
  - `cnos.loadProjection(path)`
39
+ - `cnos.registerRuntimeProvider(namespace, provider)`
39
40
  - `cnos.refreshSecrets()`
40
41
  - `cnos.refreshSecret(key)`
41
42
 
@@ -67,6 +68,49 @@ await cnos.loadProjection('./.cnos-server.json');
67
68
  await cnos.ready();
68
69
  ```
69
70
 
71
+ ## Derived Values
72
+
73
+ Derived values resolve transparently through the same read APIs.
74
+
75
+ ```yaml
76
+ app:
77
+ origin:
78
+ $derive: "${value.app.protocol}://${value.app.host}:${value.app.port}"
79
+ ```
80
+
81
+ ```ts
82
+ const origin = cnos.value('app.origin');
83
+ ```
84
+
85
+ Config-only derivations are cached for the active runtime. Runtime-dependent derivations stay live:
86
+
87
+ ```yaml
88
+ server:
89
+ effective_port:
90
+ $derive:
91
+ expr: "coalesce(process.env.PORT, value.server.default_port, '3000')"
92
+ ```
93
+
94
+ ```ts
95
+ const port = cnos.value('server.effective_port');
96
+ ```
97
+
98
+ ## Runtime Providers
99
+
100
+ Declare custom runtime namespaces in the manifest, then register a provider at runtime.
101
+
102
+ ```ts
103
+ cnos.registerRuntimeProvider('request', (key) => {
104
+ if (key === 'headers.host') {
105
+ return currentRequest?.headers.host;
106
+ }
107
+
108
+ return undefined;
109
+ });
110
+ ```
111
+
112
+ That lets server-side derived values depend on live request, session, or app-framework context without adding a second config layer.
113
+
70
114
  ## Typed values
71
115
 
72
116
  CNOS values are not limited to strings. If the underlying config stores numbers, booleans, arrays, or objects, runtime reads return those values as-is.
@@ -13,7 +13,7 @@ cnos build browser --to .cnos-browser.json
13
13
  cnos build env --profile local --to .env.local
14
14
  cnos build env --profile stage --to .env.stage
15
15
  cnos build public --framework vite --to .env.production
16
- cnos build env --profile local-domain --format docker-env --to .docker/runtime/current.env
16
+ cnos build env --profile local-domain --format docker-env --to .env.local-domain
17
17
  ```
18
18
 
19
19
  Targets:
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: cnos cache
3
+ description: Inspect and manage cached remote CNOS roots.
4
+ ---
5
+
6
+ # cnos cache
7
+
8
+ Use `cache` when a package anchor points at a remote root such as a git-backed config repo.
9
+
10
+ ```bash
11
+ cnos cache list
12
+ cnos cache clear
13
+ cnos cache clear git+https://github.com/org/config.git#v2.1.0
14
+ cnos cache refresh
15
+ cnos cache refresh git+ssh://git@github.com/org/config.git#main
16
+ ```
17
+
18
+ Subcommands:
19
+
20
+ - `cache list` shows cached remote roots, resolved commits, immutability, and size
21
+ - `cache clear` removes all cached roots or one specific cached root
22
+ - `cache refresh` forces a re-fetch for the current remote root or a specific git root URI
23
+
24
+ Notes:
25
+
26
+ - immutable refs such as semantic-version tags and commit SHAs stay cached permanently
27
+ - mutable refs such as branches are refreshed based on CNOS cache policy
28
+ - remote roots are read-only when consumed through CNOS
package/docs/cli/init.mdx CHANGED
@@ -7,5 +7,5 @@ description: Scaffold a CNOS project structure in the current repo.
7
7
 
8
8
  ```bash
9
9
  cnos init
10
- cnos init --workspace api
10
+ cnos workspace add api --package-root apps/api --extends base
11
11
  ```
@@ -9,3 +9,31 @@ description: Inspect resolved values, provenance, and overrides.
9
9
  cnos inspect value.app.name
10
10
  cnos inspect secret.app.token --reveal
11
11
  ```
12
+
13
+ `cnos inspect` also shows derived metadata.
14
+
15
+ ```bash
16
+ cnos inspect value.app.origin
17
+ ```
18
+
19
+ Typical output includes:
20
+
21
+ - resolved value
22
+ - expression or template source
23
+ - dependency keys
24
+ - whether the value is runtime-dependent
25
+ - which runtime namespaces it depends on
26
+
27
+ Example:
28
+
29
+ ```text
30
+ key: value.app.origin
31
+ value: https://api.kitsy.ai:443
32
+ derivedType: template
33
+ derivedExpression: ${value.app.protocol}://${value.app.host}:${value.app.port}
34
+ runtimeDependent: false
35
+ dependencies:
36
+ - value.app.host
37
+ - value.app.port
38
+ - value.app.protocol
39
+ ```
@@ -12,6 +12,22 @@ cnos value list --prefix app.
12
12
  cnos value delete app.name
13
13
  ```
14
14
 
15
+ ## Derived values
16
+
17
+ Use `--derive` for template shorthand:
18
+
19
+ ```bash
20
+ cnos value set app.origin --derive '${value.app.protocol}://${value.app.host}'
21
+ ```
22
+
23
+ Use `--derive --expr` for expression form:
24
+
25
+ ```bash
26
+ cnos value set app.effective_port --derive --expr "coalesce(process.env.PORT, value.app.default_port, '3000')"
27
+ ```
28
+
29
+ CNOS stores these as first-class derived values, not as opaque strings.
30
+
15
31
  ## Typed input
16
32
 
17
33
  `cnos value set` parses the input as YAML before writing it. That means you can store more than strings.
@@ -46,3 +62,4 @@ cnos read value.app.name
46
62
  - Values are private by default.
47
63
  - To expose a value to browser/public surfaces, use `cnos promote`.
48
64
  - To expose a value as shell env, map it through `envMapping.explicit` or `cnos promote --to env`.
65
+ - Derived values can be authored only under writable data namespaces such as `value.*` and custom writable data namespaces.
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: cnos workspace
3
+ description: Add, list, remove, scaffold, attach, and detach workspaces.
4
+ ---
5
+
6
+ # cnos workspace
7
+
8
+ Use `cnos workspace` when a repo has more than one app or package consuming the same CNOS root.
9
+
10
+ ## Add a workspace
11
+
12
+ ```bash
13
+ cnos workspace add travel --package-root apps/travel --extends base
14
+ ```
15
+
16
+ This updates `cnos.yml`, creates `.cnos/workspaces/travel`, and writes:
17
+
18
+ ```yaml
19
+ # apps/travel/.cnosrc.yml
20
+ root: ../../.cnos
21
+ workspace: travel
22
+ ```
23
+
24
+ ## Onboard an older single-root project into workspace mode
25
+
26
+ If a repo already has a flat `.cnos/values`, `.cnos/secrets`, `.cnos/env`, and `.cnos/profiles` tree, migrate it like this:
27
+
28
+ ```bash
29
+ cnos workspace add main --onboard-current
30
+ ```
31
+
32
+ CNOS will:
33
+
34
+ 1. move the existing flat config folders into `.cnos/workspaces/main`
35
+ 2. rewrite the root anchor to `workspace: main`
36
+ 3. keep the repo in one authoritative `.cnos` root
37
+
38
+ ## List workspaces
39
+
40
+ ```bash
41
+ cnos workspace list
42
+ cnos workspace list --json
43
+ ```
44
+
45
+ ## Remove a workspace
46
+
47
+ ```bash
48
+ cnos workspace remove gallery
49
+ ```
50
+
51
+ CNOS removes the manifest entry and deletes `.cnos/workspaces/gallery`. It refuses to remove the current default workspace until you change `workspaces.default`.
52
+
53
+ ## Scaffold wording
54
+
55
+ If your team prefers scaffold wording:
56
+
57
+ ```bash
58
+ cnos workspace scaffold insights --package-root apps/insights --extends base
59
+ ```
60
+
61
+ This follows the same creation path as `workspace add`.
62
+
63
+ ## Detach and attach
64
+
65
+ ```bash
66
+ cnos workspace detach --package-root apps/travel
67
+ cnos workspace attach --package-root apps/travel
68
+ ```
69
+
70
+ Detach makes a child package independent. Attach imports it back into the parent workspace model.
@@ -34,6 +34,14 @@ console.log(runtime.value('app.name'));
34
34
  console.log(runtime.read<string[]>('value.api.default_query_params'));
35
35
  ```
36
36
 
37
+ If your repo grows into multiple apps or packages, switch to workspace mode instead of duplicating `.cnos` trees:
38
+
39
+ ```bash
40
+ cnos workspace add main --package-root apps/main --extends base
41
+ cnos workspace add insights --package-root apps/insights --extends base
42
+ cnos workspace list
43
+ ```
44
+
37
45
  If your repo still expects env files, keep `.cnos` as the source of truth and generate them:
38
46
 
39
47
  ```bash
@@ -26,6 +26,13 @@ cnos profile create stage
26
26
  cnos use --profile stage
27
27
  ```
28
28
 
29
+ If this later becomes a monorepo, do not create a second `.cnos`. Add workspaces instead:
30
+
31
+ ```bash
32
+ cnos workspace add api --package-root apps/api --extends base
33
+ cnos workspace add admin --package-root apps/admin --extends base
34
+ ```
35
+
29
36
  Create a local vault and authenticate it:
30
37
 
31
38
  ```bash
@@ -30,6 +30,31 @@ const port = cnos.value('server.port');
30
30
  const token = cnos.secret('app.token');
31
31
  ```
32
32
 
33
+ Derived server config stays inside CNOS too:
34
+
35
+ ```yaml
36
+ server:
37
+ effective_port:
38
+ $derive:
39
+ expr: "coalesce(process.env.PORT, value.server.default_port, '3000')"
40
+ ```
41
+
42
+ ```ts
43
+ const port = cnos.value('server.effective_port');
44
+ ```
45
+
46
+ If you need live request or session context, declare a runtime namespace and register a provider:
47
+
48
+ ```ts
49
+ cnos.registerRuntimeProvider('request', (key) => {
50
+ if (key === 'headers.host') {
51
+ return currentRequest?.headers.host;
52
+ }
53
+
54
+ return undefined;
55
+ });
56
+ ```
57
+
33
58
  Env export bridge:
34
59
 
35
60
  ```bash
@@ -0,0 +1,130 @@
1
+ ---
2
+ title: Derived Values
3
+ description: Compute config from other CNOS keys and live runtime namespaces.
4
+ ---
5
+
6
+ # Derived Values
7
+
8
+ Derived values let you keep config composition inside CNOS instead of re-implementing it in app code.
9
+
10
+ Template shorthand:
11
+
12
+ ```yaml
13
+ app:
14
+ origin:
15
+ $derive: "${value.app.protocol}://${value.app.host}:${value.app.port}"
16
+ ```
17
+
18
+ Expression form:
19
+
20
+ ```yaml
21
+ app:
22
+ effective_port:
23
+ $derive:
24
+ expr: "coalesce(process.env.PORT, value.app.default_port, '3000')"
25
+ ```
26
+
27
+ ## Write from the CLI
28
+
29
+ ```bash
30
+ cnos value set app.origin --derive '${value.app.protocol}://${value.app.host}'
31
+ cnos value set app.effective_port --derive --expr "coalesce(process.env.PORT, value.app.default_port, '3000')"
32
+ ```
33
+
34
+ ## Built-ins
35
+
36
+ Supported functions:
37
+
38
+ - `concat(...)`
39
+ - `coalesce(...)`
40
+ - `when(condition, thenValue, elseValue)`
41
+ - `exists(ref)`
42
+ - `eq(a, b)`
43
+ - `ne(a, b)`
44
+
45
+ The language is intentionally small and safe. There is no arbitrary JavaScript execution.
46
+
47
+ ## Runtime Namespaces
48
+
49
+ `process.*` is the built-in runtime namespace. It stays live between reads.
50
+
51
+ ```yaml
52
+ app:
53
+ effective_port:
54
+ $derive:
55
+ expr: "coalesce(process.env.PORT, value.app.default_port, '3000')"
56
+ ```
57
+
58
+ Custom runtime namespaces are declared in the manifest and populated by the host app:
59
+
60
+ ```yaml
61
+ namespaces:
62
+ runtime:
63
+ request:
64
+ description: HTTP request context
65
+ server_only: true
66
+ ```
67
+
68
+ ```ts
69
+ import cnos from '@kitsy/cnos';
70
+
71
+ await cnos.ready();
72
+
73
+ cnos.registerRuntimeProvider('request', (key) => {
74
+ if (key === 'headers.host') {
75
+ return currentRequest?.headers.host;
76
+ }
77
+
78
+ return undefined;
79
+ });
80
+ ```
81
+
82
+ ## Caching Rules
83
+
84
+ - config-only derivations are cached once per resolution pass
85
+ - runtime-dependent derivations are never cached
86
+
87
+ That means `value.app.origin` is stable until the next `createCnos()` or `cnos.ready()`, while `value.app.effective_port` can change between reads when `process.env.PORT` changes.
88
+
89
+ ## Browser and Server Behavior
90
+
91
+ Browser/public outputs always need concrete values.
92
+
93
+ - config-only derived values can be promoted and embedded normally
94
+ - runtime-dependent derived values that rely on server-only namespaces are rejected for browser/public builds
95
+
96
+ Server projections split the result:
97
+
98
+ - `values` contains concrete non-secret values, including config-only derivations
99
+ - `derived` contains live runtime-dependent formulas
100
+ - `runtimeNamespaces` lists which runtime providers the server runtime needs
101
+
102
+ ## Use Cases
103
+
104
+ Cross-app browser links:
105
+
106
+ ```yaml
107
+ apps:
108
+ cnos:
109
+ origin:
110
+ $derive: "${value.platform.protocol}://${value.apps.cnos.host}"
111
+
112
+ public:
113
+ promote:
114
+ - value.apps.cnos.origin
115
+ ```
116
+
117
+ ```ts
118
+ import cnos from '@kitsy/cnos/browser';
119
+
120
+ const cnosOrigin = cnos('public.apps.cnos.origin');
121
+ ```
122
+
123
+ Server fallback port:
124
+
125
+ ```yaml
126
+ server:
127
+ port:
128
+ $derive:
129
+ expr: "coalesce(process.env.PORT, value.server.default_port, '3000')"
130
+ ```
@@ -40,6 +40,58 @@ console.log(cnos('public.app.apiBaseUrl'));
40
40
  console.log(import.meta.env.VITE_APP_API_BASE_URL);
41
41
  ```
42
42
 
43
+ Cross-app browser links work the same way. Put the browser-safe origins in CNOS, promote them, and let the Vite plugin handle the embedding:
44
+
45
+ ```yaml
46
+ public:
47
+ promote:
48
+ - value.apps.main.origin
49
+ - value.apps.cnos.origin
50
+ - value.apps.coop.origin
51
+ ```
52
+
53
+ ```yaml
54
+ apps:
55
+ main:
56
+ origin: https://kitsy.ai
57
+ cnos:
58
+ origin: https://cnos.kitsy.ai
59
+ coop:
60
+ origin: https://coop.kitsy.ai
61
+ ```
62
+
63
+ Then in UI code:
64
+
65
+ ```ts
66
+ import cnos from '@kitsy/cnos/browser';
67
+
68
+ const cnosOrigin = cnos('public.apps.cnos.origin');
69
+ const coopOrigin = cnos('public.apps.coop.origin');
70
+ ```
71
+
72
+ That is the point of the integration. You promote once, keep using the same logical reads in UI code, and `@kitsy/cnos-vite` makes sure the values are already present in the browser bundle.
73
+
74
+ Derived public values work the same way as long as they are build-safe:
75
+
76
+ ```yaml
77
+ apps:
78
+ cnos:
79
+ origin:
80
+ $derive: "${value.platform.protocol}://${value.apps.cnos.host}"
81
+
82
+ public:
83
+ promote:
84
+ - value.apps.cnos.origin
85
+ ```
86
+
87
+ ```ts
88
+ import cnos from '@kitsy/cnos/browser';
89
+
90
+ const cnosOrigin = cnos('public.apps.cnos.origin');
91
+ ```
92
+
93
+ If a promoted derived value depends on a server-only runtime namespace such as `process.*` or a custom `request.*`, CNOS rejects the browser/public build instead of leaking an unstable value.
94
+
43
95
  Migration path:
44
96
 
45
97
  1. keep `VITE_*` working through generated env files
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: Remote Roots
3
+ description: Point .cnosrc.yml at a remote git-backed CNOS root and consume it through the local cache.
4
+ ---
5
+
6
+ # Remote Roots
7
+
8
+ `.cnosrc.yml` can point at either a local `.cnos` directory or a remote git-backed root.
9
+
10
+ Local:
11
+
12
+ ```yaml
13
+ root: ./.cnos
14
+ ```
15
+
16
+ Remote:
17
+
18
+ ```yaml
19
+ root: git+https://github.com/org/config.git#v2.1.0
20
+ workspace: travel
21
+ ```
22
+
23
+ Remote roots are resolved into the CNOS cache, then loaded exactly like a local manifest root.
24
+
25
+ ## Supported URIs
26
+
27
+ Recommended production form:
28
+
29
+ ```yaml
30
+ root: git+https://github.com/org/config.git#v2.1.0
31
+ ```
32
+
33
+ Private repo over SSH:
34
+
35
+ ```yaml
36
+ root: git+ssh://git@github.com/org/private-config.git#main
37
+ ```
38
+
39
+ Subpath inside the repo:
40
+
41
+ ```yaml
42
+ root: git+https://github.com/org/monorepo.git#v2.1.0:config/.cnos
43
+ ```
44
+
45
+ ## Cache Behavior
46
+
47
+ - semantic-version tags and commit SHAs are treated as immutable
48
+ - branch refs are treated as mutable
49
+ - runtime reads use a cache TTL
50
+ - `cnos build` refreshes mutable refs before building artifacts
51
+ - `cnos cache refresh` forces a re-fetch when needed
52
+
53
+ Inspect the cache:
54
+
55
+ ```bash
56
+ cnos cache list
57
+ ```
58
+
59
+ Override TTL for one command when needed:
60
+
61
+ ```bash
62
+ cnos read value.app.name --cache-ttl 0
63
+ cnos watch --cache-ttl 15 -- node server.js
64
+ ```
65
+
66
+ ## Read-Only Model
67
+
68
+ Remote roots are consumed as read-only config.
69
+
70
+ These work:
71
+
72
+ ```bash
73
+ cnos read value.app.name
74
+ cnos build env --to .env.stage
75
+ cnos run -- node server.js
76
+ ```
77
+
78
+ These are blocked:
79
+
80
+ ```bash
81
+ cnos value set app.name demo
82
+ cnos promote value.app.name --to public
83
+ cnos vault create default
84
+ ```
85
+
86
+ The right workflow is to edit the source config repo and then let consumers refresh the cached root.
@@ -22,6 +22,13 @@ root: ../../.cnos
22
22
  workspace: travel
23
23
  ```
24
24
 
25
+ Child app from a remote config repo:
26
+
27
+ ```yaml
28
+ root: git+https://github.com/org/config.git#v2.1.0
29
+ workspace: travel
30
+ ```
31
+
25
32
  `.cnosrc.yml` is the only discovery anchor. CNOS does not walk upward looking for `.cnos` directories. It looks for `.cnosrc.yml` within a bounded package-root search window, then resolves the real `.cnos` root from there.
26
33
 
27
34
  Typical manifest shape:
@@ -39,6 +46,43 @@ workspaces:
39
46
 
40
47
  This lets you keep shared values in `root` and override only what each app needs in `travel`, `food`, or other child workspaces.
41
48
 
49
+ ## Day-to-day workspace management
50
+
51
+ Add a new app workspace:
52
+
53
+ ```bash
54
+ cnos workspace add insights --package-root apps/insights --extends root
55
+ cnos workspace add gallery --package-root apps/gallery --extends root
56
+ ```
57
+
58
+ List what exists:
59
+
60
+ ```bash
61
+ cnos workspace list
62
+ ```
63
+
64
+ Remove one later:
65
+
66
+ ```bash
67
+ cnos workspace remove gallery
68
+ ```
69
+
70
+ ## Migrating an older single-root repo into workspace mode
71
+
72
+ If a repo was initialized earlier with:
73
+
74
+ ```bash
75
+ cnos init
76
+ ```
77
+
78
+ and the current config still lives directly under `.cnos/values`, `.cnos/secrets`, `.cnos/env`, and `.cnos/profiles`, move that existing config into a real workspace with:
79
+
80
+ ```bash
81
+ cnos workspace add main --onboard-current
82
+ ```
83
+
84
+ CNOS will move the physical folders into `.cnos/workspaces/main` and rewrite the local anchor so the repo now behaves as a workspace-aware project.
85
+
42
86
  Read from an app package without passing a root manually:
43
87
 
44
88
  ```ts
@@ -12,6 +12,7 @@ Primary namespaces:
12
12
  - `meta.*`
13
13
  - `process.*` for server-only ambient runtime state
14
14
  - custom data namespaces such as `flags.*` or `config.*` when declared in `.cnos/cnos.yml`
15
+ - custom runtime namespaces declared under `namespaces.runtime`
15
16
 
16
17
  Derived surfaces:
17
18
 
@@ -35,3 +36,36 @@ Custom data namespaces can be:
35
36
  - `process.env.PATH`
36
37
 
37
38
  `process.*` cannot be promoted or exported.
39
+
40
+ ## Runtime Namespaces
41
+
42
+ Runtime namespaces are not populated from config files. They are declared in the manifest and populated by the host runtime.
43
+
44
+ ```yaml
45
+ namespaces:
46
+ runtime:
47
+ request:
48
+ description: HTTP request context
49
+ server_only: true
50
+ ```
51
+
52
+ Use them from derived values:
53
+
54
+ ```yaml
55
+ app:
56
+ current_host:
57
+ $derive:
58
+ expr: "coalesce(request.headers.host, value.app.default_host)"
59
+ ```
60
+
61
+ And register providers in server code:
62
+
63
+ ```ts
64
+ cnos.registerRuntimeProvider('request', (key) => {
65
+ if (key === 'headers.host') {
66
+ return currentRequest?.headers.host;
67
+ }
68
+
69
+ return undefined;
70
+ });
71
+ ```
package/manifest.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  product: cnos
2
2
  title: CNOS Documentation
3
3
  tagline: Configuration orchestration for apps, monorepos, and deployment pipelines
4
- version: "1.5"
4
+ version: "1.8"
5
5
 
6
6
  sidebar:
7
7
  - group: Getting Started
@@ -33,8 +33,12 @@ sidebar:
33
33
  label: Containers and Actions
34
34
  - path: guides/workspaces
35
35
  label: Workspaces and Monorepos
36
+ - path: guides/remote-roots
37
+ label: Remote Roots
36
38
  - path: guides/profiles
37
39
  label: Profiles and Environments
40
+ - path: guides/derived-values
41
+ label: Derived Values
38
42
  - path: guides/secrets
39
43
  label: Secrets and Vaults
40
44
  - path: guides/migration
@@ -49,6 +53,8 @@ sidebar:
49
53
  label: Overview
50
54
  - path: cli/init
51
55
  label: cnos init
56
+ - path: cli/workspace
57
+ label: cnos workspace
52
58
  - path: cli/value
53
59
  label: cnos value
54
60
  - path: cli/secret
@@ -63,6 +69,8 @@ sidebar:
63
69
  label: cnos export
64
70
  - path: cli/build
65
71
  label: cnos build env
72
+ - path: cli/cache
73
+ label: cnos cache
66
74
  - path: cli/dev
67
75
  label: cnos dev env
68
76
  - path: cli/run
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitsy/cnos-docs",
3
- "version": "1.6.1",
3
+ "version": "1.8.0",
4
4
  "description": "Source-of-truth CNOS documentation content for Astro Starlight and other static docs consumers.",
5
5
  "type": "module",
6
6
  "exports": {