@opensip-cli/config 0.1.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.
Files changed (56) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +31 -0
  4. package/dist/capability-preferences.d.ts +39 -0
  5. package/dist/capability-preferences.d.ts.map +1 -0
  6. package/dist/capability-preferences.js +61 -0
  7. package/dist/capability-preferences.js.map +1 -0
  8. package/dist/composer.d.ts +58 -0
  9. package/dist/composer.d.ts.map +1 -0
  10. package/dist/composer.js +111 -0
  11. package/dist/composer.js.map +1 -0
  12. package/dist/declaration.d.ts +59 -0
  13. package/dist/declaration.d.ts.map +1 -0
  14. package/dist/declaration.js +15 -0
  15. package/dist/declaration.js.map +1 -0
  16. package/dist/document/cli-config.d.ts +102 -0
  17. package/dist/document/cli-config.d.ts.map +1 -0
  18. package/dist/document/cli-config.js +150 -0
  19. package/dist/document/cli-config.js.map +1 -0
  20. package/dist/document/dashboard.d.ts +21 -0
  21. package/dist/document/dashboard.d.ts.map +1 -0
  22. package/dist/document/dashboard.js +21 -0
  23. package/dist/document/dashboard.js.map +1 -0
  24. package/dist/document/global-config.d.ts +101 -0
  25. package/dist/document/global-config.d.ts.map +1 -0
  26. package/dist/document/global-config.js +163 -0
  27. package/dist/document/global-config.js.map +1 -0
  28. package/dist/document/host-declarations.d.ts +44 -0
  29. package/dist/document/host-declarations.d.ts.map +1 -0
  30. package/dist/document/host-declarations.js +48 -0
  31. package/dist/document/host-declarations.js.map +1 -0
  32. package/dist/document/targeting.d.ts +151 -0
  33. package/dist/document/targeting.d.ts.map +1 -0
  34. package/dist/document/targeting.js +71 -0
  35. package/dist/document/targeting.js.map +1 -0
  36. package/dist/document/template.d.ts +43 -0
  37. package/dist/document/template.d.ts.map +1 -0
  38. package/dist/document/template.js +63 -0
  39. package/dist/document/template.js.map +1 -0
  40. package/dist/index.d.ts +39 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +37 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/json-schema.d.ts +23 -0
  45. package/dist/json-schema.d.ts.map +1 -0
  46. package/dist/json-schema.js +25 -0
  47. package/dist/json-schema.js.map +1 -0
  48. package/dist/namespace-claims.d.ts +29 -0
  49. package/dist/namespace-claims.d.ts.map +1 -0
  50. package/dist/namespace-claims.js +62 -0
  51. package/dist/namespace-claims.js.map +1 -0
  52. package/dist/precedence.d.ts +47 -0
  53. package/dist/precedence.d.ts.map +1 -0
  54. package/dist/precedence.js +103 -0
  55. package/dist/precedence.js.map +1 -0
  56. package/package.json +47 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * cli-config — the tool-agnostic `cli:` block of `opensip-cli.config.yml`.
3
+ *
4
+ * Owns three things, all relocated here under ADR-0023 §Amendment:
5
+ * - {@link CliDefaults} — the structural type the CLI pre-action hook reads.
6
+ * - {@link loadCliDefaults} — the permissive loader the hook calls to merge
7
+ * project-wide defaults (`--report-to`, `--exclude`, `--json`, `--api-key`,
8
+ * `verbose`, `debug`, the `cli.cloud` sync block) into Commander opts.
9
+ * - {@link cliConfigSchema} — the Zod schema the host registers as the `cli`
10
+ * document-level declaration so the composed whole-document validation
11
+ * STRICT-rejects a typo in `cli:` before dispatch.
12
+ *
13
+ * Previously this lived in `@opensip-cli/contracts` (`cli-config.ts`) — a
14
+ * runtime YAML projection in a types-only package (the standing charter
15
+ * violation ADR-0023 names). It now lives in the config layer, beside the rest
16
+ * of the document blocks. The generic `readYamlFile` / `resolveProjectConfigPath`
17
+ * primitives stay in `core` (path/read primitives — the config-resolution
18
+ * decision in the ADR amendment); this module imports them from core.
19
+ *
20
+ * The loader is deliberately permissive — missing config, malformed YAML, or an
21
+ * absent `cli:` key all return `{}`. Strict validation is the composed
22
+ * document's job (the `cli` host declaration), not this reader's.
23
+ */
24
+ import { z } from 'zod';
25
+ /**
26
+ * Shape of the `cli:` block in `opensip-cli.config.yml` as the CLI pre-action
27
+ * hook reads it. The structural mirror of {@link cliConfigSchema}.
28
+ */
29
+ export interface CliDefaults {
30
+ readonly exclude?: readonly string[];
31
+ readonly verbose?: boolean;
32
+ readonly json?: boolean;
33
+ readonly reportTo?: string;
34
+ readonly apiKey?: string;
35
+ readonly fileTypes?: readonly string[];
36
+ readonly ignore?: readonly string[];
37
+ readonly debug?: boolean;
38
+ /**
39
+ * Presentation settings (the `cli.ui:` sub-block). Currently just the
40
+ * banner size shown above each command. Unlike the other defaults this
41
+ * does NOT map onto a Commander flag — there is no `--banner`; it rides
42
+ * on `RunScope.ui` and is read by the render paths directly.
43
+ */
44
+ readonly ui?: {
45
+ /** Banner art: `mini` (default) | `lg` | `md` | `sm`. */
46
+ readonly banner?: 'lg' | 'md' | 'sm' | 'mini';
47
+ };
48
+ /**
49
+ * OpenSIP Cloud signal sync (ADR-0008). When the customer has an API key
50
+ * and is entitled to the storage tier, each run additionally emits its
51
+ * signals to OpenSIP Cloud (best-effort; local SQLite is unaffected).
52
+ * `sync` defaults to `true` when entitled — set `false` to opt out.
53
+ * `endpoint` overrides the built-in OpenSIP Cloud URL (must be https).
54
+ */
55
+ readonly cloud?: {
56
+ readonly sync?: boolean;
57
+ readonly endpoint?: string;
58
+ };
59
+ }
60
+ /**
61
+ * The Zod schema for the `cli:` document-level block. A superset of the legacy
62
+ * fitness `CliDefaultsSchema` (it additionally claims `debug` and the
63
+ * `cli.cloud` sub-block the permissive loader always read) so the composed
64
+ * STRICT validation never rejects a key the loader honours. Strictness is
65
+ * applied at the document level by the composer (`.strict()` on the namespace),
66
+ * so nested `ui`/`cloud` objects stay lenient — matching prior behaviour.
67
+ */
68
+ export declare const cliConfigSchema: z.ZodObject<{
69
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
+ verbose: z.ZodOptional<z.ZodBoolean>;
71
+ json: z.ZodOptional<z.ZodBoolean>;
72
+ reportTo: z.ZodOptional<z.ZodURL>;
73
+ apiKey: z.ZodOptional<z.ZodString>;
74
+ fileTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
75
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
76
+ debug: z.ZodOptional<z.ZodBoolean>;
77
+ ui: z.ZodOptional<z.ZodObject<{
78
+ banner: z.ZodOptional<z.ZodEnum<{
79
+ lg: "lg";
80
+ md: "md";
81
+ sm: "sm";
82
+ mini: "mini";
83
+ }>>;
84
+ }, z.core.$strip>>;
85
+ cloud: z.ZodOptional<z.ZodObject<{
86
+ sync: z.ZodOptional<z.ZodBoolean>;
87
+ endpoint: z.ZodOptional<z.ZodString>;
88
+ }, z.core.$strip>>;
89
+ }, z.core.$strip>;
90
+ /**
91
+ * Best-effort load of the `cli:` block from `opensip-cli.config.yml`.
92
+ * Resolves the file via the core `resolveProjectConfigPath` primitive.
93
+ *
94
+ * Returns `{}` when the config is missing, unreadable, malformed, or has no
95
+ * `cli:` section — the merge step treats absence and "everything default" the
96
+ * same.
97
+ *
98
+ * @param cwd Project root for config resolution.
99
+ * @param explicitPath Optional `--config <path>` override.
100
+ */
101
+ export declare function loadCliDefaults(cwd: string, explicitPath?: string): CliDefaults;
102
+ //# sourceMappingURL=cli-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-config.d.ts","sourceRoot":"","sources":["../../src/document/cli-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE;QACZ,yDAAyD;QACzD,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;KAC/C,CAAC;IACF;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;iBAoB1B,CAAC;AA6DH;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAa/E"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * cli-config — the tool-agnostic `cli:` block of `opensip-cli.config.yml`.
3
+ *
4
+ * Owns three things, all relocated here under ADR-0023 §Amendment:
5
+ * - {@link CliDefaults} — the structural type the CLI pre-action hook reads.
6
+ * - {@link loadCliDefaults} — the permissive loader the hook calls to merge
7
+ * project-wide defaults (`--report-to`, `--exclude`, `--json`, `--api-key`,
8
+ * `verbose`, `debug`, the `cli.cloud` sync block) into Commander opts.
9
+ * - {@link cliConfigSchema} — the Zod schema the host registers as the `cli`
10
+ * document-level declaration so the composed whole-document validation
11
+ * STRICT-rejects a typo in `cli:` before dispatch.
12
+ *
13
+ * Previously this lived in `@opensip-cli/contracts` (`cli-config.ts`) — a
14
+ * runtime YAML projection in a types-only package (the standing charter
15
+ * violation ADR-0023 names). It now lives in the config layer, beside the rest
16
+ * of the document blocks. The generic `readYamlFile` / `resolveProjectConfigPath`
17
+ * primitives stay in `core` (path/read primitives — the config-resolution
18
+ * decision in the ADR amendment); this module imports them from core.
19
+ *
20
+ * The loader is deliberately permissive — missing config, malformed YAML, or an
21
+ * absent `cli:` key all return `{}`. Strict validation is the composed
22
+ * document's job (the `cli` host declaration), not this reader's.
23
+ */
24
+ import { readYamlFile, resolveProjectConfigPath } from '@opensip-cli/core';
25
+ import { z } from 'zod';
26
+ /**
27
+ * The Zod schema for the `cli:` document-level block. A superset of the legacy
28
+ * fitness `CliDefaultsSchema` (it additionally claims `debug` and the
29
+ * `cli.cloud` sub-block the permissive loader always read) so the composed
30
+ * STRICT validation never rejects a key the loader honours. Strictness is
31
+ * applied at the document level by the composer (`.strict()` on the namespace),
32
+ * so nested `ui`/`cloud` objects stay lenient — matching prior behaviour.
33
+ */
34
+ export const cliConfigSchema = z.object({
35
+ exclude: z.array(z.string()).optional(),
36
+ verbose: z.boolean().optional(),
37
+ json: z.boolean().optional(),
38
+ reportTo: z.url().optional(),
39
+ apiKey: z.string().min(1).optional(),
40
+ fileTypes: z.array(z.string()).optional(),
41
+ ignore: z.array(z.string()).optional(),
42
+ debug: z.boolean().optional(),
43
+ ui: z
44
+ .object({
45
+ banner: z.enum(['lg', 'md', 'sm', 'mini']).optional(),
46
+ })
47
+ .optional(),
48
+ cloud: z
49
+ .object({
50
+ sync: z.boolean().optional(),
51
+ endpoint: z.string().optional(),
52
+ })
53
+ .optional(),
54
+ });
55
+ /** Valid `ui.banner` values; anything else is dropped (→ default applies). */
56
+ const BANNER_VALUES = new Set(['lg', 'md', 'sm', 'mini']);
57
+ /**
58
+ * Type guard for permissive YAML reading. We accept anything that
59
+ * looks like a plain object; everything else collapses to `{}`.
60
+ */
61
+ function isPlainObject(v) {
62
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
63
+ }
64
+ /** Coerce a YAML value into a `string[]` if it is one; otherwise drop it. */
65
+ function asStringArray(value) {
66
+ if (!Array.isArray(value))
67
+ return undefined;
68
+ if (!value.every((v) => typeof v === 'string'))
69
+ return undefined;
70
+ return value;
71
+ }
72
+ /** Project an arbitrary YAML object into the typed `CliDefaults` shape. */
73
+ function projectCliDefaults(raw) {
74
+ const out = {};
75
+ const exclude = asStringArray(raw.exclude);
76
+ if (exclude)
77
+ out.exclude = exclude;
78
+ if (typeof raw.verbose === 'boolean')
79
+ out.verbose = raw.verbose;
80
+ if (typeof raw.json === 'boolean')
81
+ out.json = raw.json;
82
+ if (typeof raw.reportTo === 'string')
83
+ out.reportTo = raw.reportTo;
84
+ if (typeof raw.apiKey === 'string')
85
+ out.apiKey = raw.apiKey;
86
+ const fileTypes = asStringArray(raw.fileTypes);
87
+ if (fileTypes)
88
+ out.fileTypes = fileTypes;
89
+ const ignore = asStringArray(raw.ignore);
90
+ if (ignore)
91
+ out.ignore = ignore;
92
+ if (typeof raw.debug === 'boolean')
93
+ out.debug = raw.debug;
94
+ const ui = projectUiDefaults(raw.ui);
95
+ if (ui)
96
+ out.ui = ui;
97
+ const cloud = projectCloudDefaults(raw.cloud);
98
+ if (cloud)
99
+ out.cloud = cloud;
100
+ return out;
101
+ }
102
+ /** Project the `cli.cloud:` sub-block (sync flag + endpoint override) into the typed shape. */
103
+ function projectCloudDefaults(raw) {
104
+ if (!isPlainObject(raw))
105
+ return undefined;
106
+ const out = {};
107
+ if (typeof raw.sync === 'boolean')
108
+ out.sync = raw.sync;
109
+ if (typeof raw.endpoint === 'string')
110
+ out.endpoint = raw.endpoint;
111
+ return out.sync === undefined && out.endpoint === undefined ? undefined : out;
112
+ }
113
+ /** Project the `cli.ui:` sub-block into the typed shape; drop unknown banner values. */
114
+ function projectUiDefaults(raw) {
115
+ if (!isPlainObject(raw))
116
+ return undefined;
117
+ if (typeof raw.banner === 'string' && BANNER_VALUES.has(raw.banner)) {
118
+ return { banner: raw.banner };
119
+ }
120
+ return undefined;
121
+ }
122
+ /**
123
+ * Best-effort load of the `cli:` block from `opensip-cli.config.yml`.
124
+ * Resolves the file via the core `resolveProjectConfigPath` primitive.
125
+ *
126
+ * Returns `{}` when the config is missing, unreadable, malformed, or has no
127
+ * `cli:` section — the merge step treats absence and "everything default" the
128
+ * same.
129
+ *
130
+ * @param cwd Project root for config resolution.
131
+ * @param explicitPath Optional `--config <path>` override.
132
+ */
133
+ export function loadCliDefaults(cwd, explicitPath) {
134
+ let filePath;
135
+ try {
136
+ filePath = resolveProjectConfigPath(cwd, explicitPath);
137
+ }
138
+ catch {
139
+ // @fitness-ignore-next-line error-handling-quality -- documented contract (see JSDoc above): failure to resolve the project config is equivalent to "no cli: section" and treated identically by the merge step.
140
+ return {};
141
+ }
142
+ const doc = readYamlFile(filePath);
143
+ if (!isPlainObject(doc))
144
+ return {};
145
+ const cliBlock = doc.cli;
146
+ if (!isPlainObject(cliBlock))
147
+ return {};
148
+ return projectCliDefaults(cliBlock);
149
+ }
150
+ //# sourceMappingURL=cli-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-config.js","sourceRoot":"","sources":["../../src/document/cli-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * dashboard — the `dashboard:` document-level block of
3
+ * `opensip-cli.config.yml`.
4
+ *
5
+ * Currently just the editor protocol used by the Code Paths panel to build
6
+ * `vscode://` / `cursor://` deep links. `dashboard` is a CLI-owned
7
+ * composition-root command, not a Tool plugin (ADR-0023 §Amendment), so its
8
+ * config is a host document-level block — structurally identical to `cli`,
9
+ * registered beside it in {@link ./host-declarations}.
10
+ *
11
+ * Relocated here from fitness's `SignalersConfigSchema`. Fitness
12
+ * still reads `dashboard.editor` via `loadSignalersConfig` until it is repointed
13
+ * to the composed scope config (Phase 4); it imports this schema rather than
14
+ * re-defining it, so there is one definition of the block.
15
+ */
16
+ import { z } from 'zod';
17
+ /** The Zod schema for the `dashboard:` document-level block. */
18
+ export declare const dashboardConfigSchema: z.ZodObject<{
19
+ editor: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>;
21
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/document/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gEAAgE;AAChE,eAAO,MAAM,qBAAqB;;iBAEhC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * dashboard — the `dashboard:` document-level block of
3
+ * `opensip-cli.config.yml`.
4
+ *
5
+ * Currently just the editor protocol used by the Code Paths panel to build
6
+ * `vscode://` / `cursor://` deep links. `dashboard` is a CLI-owned
7
+ * composition-root command, not a Tool plugin (ADR-0023 §Amendment), so its
8
+ * config is a host document-level block — structurally identical to `cli`,
9
+ * registered beside it in {@link ./host-declarations}.
10
+ *
11
+ * Relocated here from fitness's `SignalersConfigSchema`. Fitness
12
+ * still reads `dashboard.editor` via `loadSignalersConfig` until it is repointed
13
+ * to the composed scope config (Phase 4); it imports this schema rather than
14
+ * re-defining it, so there is one definition of the block.
15
+ */
16
+ import { z } from 'zod';
17
+ /** The Zod schema for the `dashboard:` document-level block. */
18
+ export const dashboardConfigSchema = z.object({
19
+ editor: z.string().min(1).max(64).optional(),
20
+ });
21
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/document/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gEAAgE;AAChE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * global-config — read/write the user-level (`~/.opensip-cli/config.yml`)
3
+ * config that holds the cloud API key and per-user defaults.
4
+ *
5
+ * User-scoped config I/O is tool-agnostic, so it lives in the config layer
6
+ * (relocated here from the CLI's `bootstrap/`, ADR-0023). The CLI's
7
+ * pre-action hook reads it on every invocation (`mergeConfigDefaults` falls back
8
+ * to the saved API key when neither `--api-key` nor `OPENSIP_API_KEY` is
9
+ * present), and the `configure` command's prompt+UX wrapper — which stays in
10
+ * `cli/commands` — reads/writes I/O through this module.
11
+ *
12
+ * The file is YAML and is `chmod 0o600` on write — it stores a secret.
13
+ * Reads are tolerant of any failure (missing dir, malformed YAML); the
14
+ * pre-action hook treats absence and corruption the same as "no key
15
+ * configured".
16
+ */
17
+ import { type EnvVarSpec } from '@opensip-cli/core';
18
+ /**
19
+ * Config-layer environment variables (§5.12). Declared as an
20
+ * immutable spec table read through the {@link EnvRegistry} primitive, so the env
21
+ * surface is governed and documentable (the `env-via-registry` guardrail forbids
22
+ * raw `process.env` reads). Re-exported for the generated env-surface doc.
23
+ */
24
+ export declare const CONFIG_ENV_SPECS: readonly EnvVarSpec<unknown>[];
25
+ /** User-level config file path. */
26
+ export declare const GLOBAL_CONFIG_PATH: string;
27
+ /**
28
+ * Shape of `~/.opensip-cli/config.yml`. Open-ended on purpose — future
29
+ * per-user defaults (theme, last-used recipe, telemetry opt-in) can land
30
+ * here without a contract change.
31
+ */
32
+ export interface GlobalConfig {
33
+ apiKey?: string;
34
+ /**
35
+ * User-level OpenSIP Cloud signal-sync control (ADR-0008). This is the
36
+ * machine-wide privacy opt-out: `cloud.sync: false` here disables signal
37
+ * sync for every project run from this account, regardless of any project's
38
+ * own `cli.cloud:` setting. `endpoint` overrides the cloud URL per user.
39
+ */
40
+ cloud?: {
41
+ sync?: boolean;
42
+ endpoint?: string;
43
+ };
44
+ [key: string]: unknown;
45
+ }
46
+ /**
47
+ * Read the user-level global config. Returns `{}` on any failure
48
+ * (missing file, malformed YAML, I/O error) — the merge step treats
49
+ * absence and "everything default" the same.
50
+ */
51
+ export declare function readGlobalConfig(): GlobalConfig;
52
+ /**
53
+ * Persist the user-level global config. Creates the parent directory if
54
+ * it doesn't exist, then writes via a same-directory temp file with mode
55
+ * `0o600` set at creation time and atomically renames into place.
56
+ *
57
+ * Why temp + rename instead of writeFile + chmod: writeFileSync would
58
+ * create the file using the process's umask (commonly 0o644), leaving a
59
+ * race window during which another local user could read the API key
60
+ * before chmodSync(..., 0o600) tightens permissions. openSync with mode
61
+ * 0o600 + O_EXCL ('wx') sets the permission atomically with the inode
62
+ * creation, and rename publishes the fully-written file in one step so
63
+ * readers never observe a partial file either.
64
+ */
65
+ export declare function writeGlobalConfig(config: GlobalConfig): void;
66
+ /**
67
+ * Resolve the OpenSIP Cloud API key from the highest-precedence source
68
+ * available. Resolution order:
69
+ *
70
+ * 1. CLI flag (`--api-key`).
71
+ * 2. Environment variable (`OPENSIP_API_KEY`).
72
+ * 3. User-level global config (`~/.opensip-cli/config.yml#apiKey`).
73
+ *
74
+ * The pre-action hook calls this for the global merge step; the
75
+ * `configure` command calls it for the "current key" hint at the
76
+ * prompt.
77
+ */
78
+ export declare function resolveApiKey(cliFlag?: string): string | undefined;
79
+ /**
80
+ * Resolve the effective cloud config for a run by layering the user-level
81
+ * cloud block (`~/.opensip-cli/config.yml#cloud`) over the project-level
82
+ * `cli.cloud:` block — the missing piece behind audit P0-2, where the
83
+ * documented user opt-out was read for the API key but never for `cloud`.
84
+ *
85
+ * Semantics (a data-egress control, so opt-out is sticky):
86
+ * - `sync` is `false` if EITHER the user (privacy opt-out) or the project
87
+ * (policy opt-out) sets it `false` — the more restrictive wins, neither
88
+ * silently overrides the other. Otherwise the user's explicit value, then
89
+ * the project's.
90
+ * - `endpoint` takes the user override, then the project's.
91
+ * - the per-invocation `--no-cloud` flag overrides everything (applied
92
+ * separately, in resolveSignalSink's `noCloud`).
93
+ */
94
+ export declare function resolveEffectiveCloudConfig(projectCloud?: {
95
+ readonly sync?: boolean;
96
+ readonly endpoint?: string;
97
+ }): {
98
+ sync?: boolean;
99
+ endpoint?: string;
100
+ } | undefined;
101
+ //# sourceMappingURL=global-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-config.d.ts","sourceRoot":"","sources":["../../src/document/global-config.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AAgBH,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGjE;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,UAAU,CAAC,OAAO,CAAC,EAK1D,CAAC;AAKF,mCAAmC;AACnC,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AAElE;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,CAQ/C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAsB5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQlE;AAaD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,CAAC,EAAE;IACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAYpD"}
@@ -0,0 +1,163 @@
1
+ // @fitness-ignore-file error-handling-quality -- readGlobalConfig returns {} on any failure by documented contract (absent file and "everything default" are equivalent to the merge step); writeGlobalConfig's inner unlink is cleanup-of-cleanup where the meaningful rename error is already thrown on the next line.
2
+ // @fitness-ignore-file unbounded-memory -- reads ~/.opensip-cli/config.yml, a small user-config file bounded by configuration shape
3
+ /**
4
+ * global-config — read/write the user-level (`~/.opensip-cli/config.yml`)
5
+ * config that holds the cloud API key and per-user defaults.
6
+ *
7
+ * User-scoped config I/O is tool-agnostic, so it lives in the config layer
8
+ * (relocated here from the CLI's `bootstrap/`, ADR-0023). The CLI's
9
+ * pre-action hook reads it on every invocation (`mergeConfigDefaults` falls back
10
+ * to the saved API key when neither `--api-key` nor `OPENSIP_API_KEY` is
11
+ * present), and the `configure` command's prompt+UX wrapper — which stays in
12
+ * `cli/commands` — reads/writes I/O through this module.
13
+ *
14
+ * The file is YAML and is `chmod 0o600` on write — it stores a secret.
15
+ * Reads are tolerant of any failure (missing dir, malformed YAML); the
16
+ * pre-action hook treats absence and corruption the same as "no key
17
+ * configured".
18
+ */
19
+ import { randomBytes } from 'node:crypto';
20
+ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeSync, } from 'node:fs';
21
+ import { homedir } from 'node:os';
22
+ import { join } from 'node:path';
23
+ import { EnvRegistry } from '@opensip-cli/core';
24
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
25
+ /**
26
+ * Config-layer environment variables (§5.12). Declared as an
27
+ * immutable spec table read through the {@link EnvRegistry} primitive, so the env
28
+ * surface is governed and documentable (the `env-via-registry` guardrail forbids
29
+ * raw `process.env` reads). Re-exported for the generated env-surface doc.
30
+ */
31
+ export const CONFIG_ENV_SPECS = [
32
+ {
33
+ canonical: 'OPENSIP_API_KEY',
34
+ docs: 'OpenSIP Cloud API key. Overrides the apiKey stored in ~/.opensip-cli/config.yml.',
35
+ },
36
+ ];
37
+ const CONFIG_ENV = new EnvRegistry(CONFIG_ENV_SPECS);
38
+ /** User-level OpenSIP root directory. */
39
+ const OPENSIP_DIR = join(homedir(), '.opensip-cli');
40
+ /** User-level config file path. */
41
+ export const GLOBAL_CONFIG_PATH = join(OPENSIP_DIR, 'config.yml');
42
+ /**
43
+ * Read the user-level global config. Returns `{}` on any failure
44
+ * (missing file, malformed YAML, I/O error) — the merge step treats
45
+ * absence and "everything default" the same.
46
+ */
47
+ export function readGlobalConfig() {
48
+ if (!existsSync(GLOBAL_CONFIG_PATH))
49
+ return {};
50
+ try {
51
+ const raw = readFileSync(GLOBAL_CONFIG_PATH, 'utf8');
52
+ return parseYaml(raw) ?? {};
53
+ }
54
+ catch {
55
+ return {};
56
+ }
57
+ }
58
+ /**
59
+ * Persist the user-level global config. Creates the parent directory if
60
+ * it doesn't exist, then writes via a same-directory temp file with mode
61
+ * `0o600` set at creation time and atomically renames into place.
62
+ *
63
+ * Why temp + rename instead of writeFile + chmod: writeFileSync would
64
+ * create the file using the process's umask (commonly 0o644), leaving a
65
+ * race window during which another local user could read the API key
66
+ * before chmodSync(..., 0o600) tightens permissions. openSync with mode
67
+ * 0o600 + O_EXCL ('wx') sets the permission atomically with the inode
68
+ * creation, and rename publishes the fully-written file in one step so
69
+ * readers never observe a partial file either.
70
+ */
71
+ export function writeGlobalConfig(config) {
72
+ if (!existsSync(OPENSIP_DIR)) {
73
+ mkdirSync(OPENSIP_DIR, { recursive: true });
74
+ }
75
+ const tmpPath = join(OPENSIP_DIR, `.config-${randomBytes(6).toString('hex')}.yml.tmp`);
76
+ const fd = openSync(tmpPath, 'wx', 0o600);
77
+ try {
78
+ writeSync(fd, stringifyYaml(config), 0, 'utf8');
79
+ }
80
+ finally {
81
+ closeSync(fd);
82
+ }
83
+ try {
84
+ renameSync(tmpPath, GLOBAL_CONFIG_PATH);
85
+ }
86
+ catch (error) {
87
+ // Clean up the temp file on rename failure so it doesn't linger.
88
+ try {
89
+ unlinkSync(tmpPath);
90
+ }
91
+ catch {
92
+ // Swallow secondary failure — original error is the one that matters.
93
+ }
94
+ throw error;
95
+ }
96
+ }
97
+ /**
98
+ * Resolve the OpenSIP Cloud API key from the highest-precedence source
99
+ * available. Resolution order:
100
+ *
101
+ * 1. CLI flag (`--api-key`).
102
+ * 2. Environment variable (`OPENSIP_API_KEY`).
103
+ * 3. User-level global config (`~/.opensip-cli/config.yml#apiKey`).
104
+ *
105
+ * The pre-action hook calls this for the global merge step; the
106
+ * `configure` command calls it for the "current key" hint at the
107
+ * prompt.
108
+ */
109
+ export function resolveApiKey(cliFlag) {
110
+ if (cliFlag)
111
+ return cliFlag;
112
+ // Env override (read through the registry; truthy so an empty value falls
113
+ // through to the config file, byte-identical to the prior `process.env` check).
114
+ const fromEnv = CONFIG_ENV.get('OPENSIP_API_KEY');
115
+ if (fromEnv)
116
+ return fromEnv;
117
+ const config = readGlobalConfig();
118
+ return config.apiKey ?? undefined;
119
+ }
120
+ /** Read + validate the user-level `cloud:` block, defensively. */
121
+ function readUserCloudConfig() {
122
+ const raw = readGlobalConfig().cloud;
123
+ if (!raw || typeof raw !== 'object')
124
+ return undefined;
125
+ const r = raw;
126
+ const out = {};
127
+ if (typeof r.sync === 'boolean')
128
+ out.sync = r.sync;
129
+ if (typeof r.endpoint === 'string')
130
+ out.endpoint = r.endpoint;
131
+ return out.sync === undefined && out.endpoint === undefined ? undefined : out;
132
+ }
133
+ /**
134
+ * Resolve the effective cloud config for a run by layering the user-level
135
+ * cloud block (`~/.opensip-cli/config.yml#cloud`) over the project-level
136
+ * `cli.cloud:` block — the missing piece behind audit P0-2, where the
137
+ * documented user opt-out was read for the API key but never for `cloud`.
138
+ *
139
+ * Semantics (a data-egress control, so opt-out is sticky):
140
+ * - `sync` is `false` if EITHER the user (privacy opt-out) or the project
141
+ * (policy opt-out) sets it `false` — the more restrictive wins, neither
142
+ * silently overrides the other. Otherwise the user's explicit value, then
143
+ * the project's.
144
+ * - `endpoint` takes the user override, then the project's.
145
+ * - the per-invocation `--no-cloud` flag overrides everything (applied
146
+ * separately, in resolveSignalSink's `noCloud`).
147
+ */
148
+ export function resolveEffectiveCloudConfig(projectCloud) {
149
+ const userCloud = readUserCloudConfig();
150
+ if (!userCloud && !projectCloud)
151
+ return undefined;
152
+ const out = {};
153
+ const sync = userCloud?.sync === false || projectCloud?.sync === false
154
+ ? false
155
+ : (userCloud?.sync ?? projectCloud?.sync);
156
+ const endpoint = userCloud?.endpoint ?? projectCloud?.endpoint;
157
+ if (sync !== undefined)
158
+ out.sync = sync;
159
+ if (endpoint !== undefined)
160
+ out.endpoint = endpoint;
161
+ return out.sync === undefined && out.endpoint === undefined ? undefined : out;
162
+ }
163
+ //# sourceMappingURL=global-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-config.js","sourceRoot":"","sources":["../../src/document/global-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * host-declarations — the document-level config blocks owned by the host
3
+ * (the config package itself), not by any Tool plugin.
4
+ *
5
+ * Each tool contributes a namespaced {@link ToolConfigDeclaration}
6
+ * (`fitness`/`graph`/`simulation`) that the composer strict-validates. The
7
+ * tool-agnostic blocks — `cli`, `dashboard`, `schemaVersion`, `plugins`, and
8
+ * (from Phase 1) `targets`/`globalExcludes`/`checkOverrides` — are owned by no
9
+ * tool. They are returned here as `ToolConfigDeclaration`s and composed BESIDE
10
+ * the tool declarations (the composer is namespace-agnostic), turning the
11
+ * previously-`.catchall`-tolerated top-level keys into claimed, strict
12
+ * namespaces (ADR-0023).
13
+ *
14
+ * `schemaVersion` is claimed as a permissive top-level `number` so the
15
+ * composed document does not reject it — but the version-COMPAT decision
16
+ * (`readConfigSchemaVersion` + `checkSchemaCompat`) stays in `core`, run in the
17
+ * pre-action gate BEFORE validation (ADR-0023 §Amendment).
18
+ */
19
+ import { type PluginConfigKeyDeclaration } from './targeting.js';
20
+ import type { ToolConfigDeclaration } from '../declaration.js';
21
+ /**
22
+ * Options for {@link hostConfigDeclarations}.
23
+ *
24
+ * The host's document-level declarations are mostly static, but the `plugins.*`
25
+ * namespace is dynamic — a plugin may contribute its own typed config keys. The
26
+ * composition root collects those and passes them here so the composed schema
27
+ * validates declared plugin keys strictly.
28
+ */
29
+ export interface HostConfigDeclarationOptions {
30
+ /**
31
+ * Per-plugin config-key declarations discovered for this run. Each becomes a
32
+ * strictly-validated key under the `plugins.<id>` namespace. Omitted (or
33
+ * empty) when no plugin contributes config.
34
+ */
35
+ readonly pluginConfigKeys?: readonly PluginConfigKeyDeclaration[];
36
+ }
37
+ /**
38
+ * The host's document-level declarations. Grows in Phase 1 (targeting).
39
+ *
40
+ * Returned as a fresh array per call (no shared mutable state); the
41
+ * composition root concatenates these with the per-tool declarations.
42
+ */
43
+ export declare function hostConfigDeclarations(options?: HostConfigDeclarationOptions): readonly ToolConfigDeclaration[];
44
+ //# sourceMappingURL=host-declarations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-declarations.d.ts","sourceRoot":"","sources":["../../src/document/host-declarations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,EAKL,KAAK,0BAA0B,EAChC,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,0BAA0B,EAAE,CAAC;CACnE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,4BAAiC,GACzC,SAAS,qBAAqB,EAAE,CAkBlC"}