@fireweaveai/server-sdk-cjs 0.0.0-reserve.0 → 0.0.0-stage

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 (55) hide show
  1. package/README.md +2 -54
  2. package/package.json +4 -56
  3. package/LICENSE +0 -21
  4. package/dist/application/client.d.ts +0 -77
  5. package/dist/application/client.js +0 -144
  6. package/dist/application/mode.d.ts +0 -70
  7. package/dist/application/mode.js +0 -74
  8. package/dist/application/ports.d.ts +0 -94
  9. package/dist/application/ports.js +0 -2
  10. package/dist/application/runtime.d.ts +0 -101
  11. package/dist/application/runtime.js +0 -346
  12. package/dist/domain/context.d.ts +0 -67
  13. package/dist/domain/context.js +0 -90
  14. package/dist/domain/errors.d.ts +0 -45
  15. package/dist/domain/errors.js +0 -99
  16. package/dist/domain/target.d.ts +0 -2
  17. package/dist/domain/target.js +0 -2
  18. package/dist/domain/types.d.ts +0 -107
  19. package/dist/domain/types.js +0 -2
  20. package/dist/domain/validation.d.ts +0 -124
  21. package/dist/domain/validation.js +0 -355
  22. package/dist/index.d.ts +0 -34
  23. package/dist/index.js +0 -52
  24. package/dist/infrastructure/adapters/inmemory.d.ts +0 -77
  25. package/dist/infrastructure/adapters/inmemory.js +0 -151
  26. package/dist/infrastructure/adapters/local.d.ts +0 -108
  27. package/dist/infrastructure/adapters/local.js +0 -105
  28. package/dist/infrastructure/adapters/remote.d.ts +0 -74
  29. package/dist/infrastructure/adapters/remote.js +0 -373
  30. package/dist/infrastructure/hosts.d.ts +0 -18
  31. package/dist/infrastructure/hosts.js +0 -72
  32. package/dist/register-browser.d.ts +0 -1
  33. package/dist/register-browser.js +0 -7
  34. package/dist/register.d.ts +0 -1
  35. package/dist/register.js +0 -13
  36. package/dist/start/browser.d.ts +0 -12
  37. package/dist/start/browser.js +0 -36
  38. package/dist/start/build-info.d.ts +0 -2
  39. package/dist/start/build-info.js +0 -9
  40. package/dist/start/control-points.d.ts +0 -20
  41. package/dist/start/control-points.js +0 -59
  42. package/dist/start/env.d.ts +0 -11
  43. package/dist/start/env.js +0 -64
  44. package/dist/start/fw.d.ts +0 -29
  45. package/dist/start/fw.js +0 -76
  46. package/dist/start/index.d.ts +0 -23
  47. package/dist/start/index.js +0 -28
  48. package/dist/start/instance.d.ts +0 -17
  49. package/dist/start/instance.js +0 -56
  50. package/dist/start/names.d.ts +0 -22
  51. package/dist/start/names.js +0 -25
  52. package/dist/start/resolve.d.ts +0 -40
  53. package/dist/start/resolve.js +0 -139
  54. package/dist/start/state.d.ts +0 -96
  55. package/dist/start/state.js +0 -303
@@ -1,99 +0,0 @@
1
- "use strict";
2
- /**
3
- * Fireweave canonical error taxonomy (spec/errors.schema.json, contracts/errors.json).
4
- *
5
- * 15 PascalCase kinds mapped to OpenFeature error codes. Rules:
6
- * - defaults never throw: evaluation paths surface errors via Decision, not exceptions;
7
- * - no secrets in messages: all outward-facing messages are redacted;
8
- * - cause preserved internally (`FireweaveError.cause`), never serialized outward.
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.FireweaveError = exports.ERROR_TAXONOMY = void 0;
12
- exports.redactSecrets = redactSecrets;
13
- exports.isFireweaveError = isFireweaveError;
14
- const spec = (kind, openFeatureErrorCode, retryable, errorClass, defaultMessage) => ({ kind, openFeatureErrorCode, retryable, errorClass, defaultMessage });
15
- exports.ERROR_TAXONOMY = Object.freeze({
16
- NotReady: spec('NotReady', 'PROVIDER_NOT_READY', true, 'transient', 'provider not ready'),
17
- ControlPointNotFound: spec('ControlPointNotFound', 'FLAG_NOT_FOUND', false, 'permanent', 'flag not found'),
18
- TypeMismatch: spec('TypeMismatch', 'TYPE_MISMATCH', false, 'permanent', 'flag type mismatch'),
19
- InvalidContext: spec('InvalidContext', 'INVALID_CONTEXT', false, 'permanent', 'invalid evaluation context'),
20
- Authentication: spec('Authentication', 'GENERAL', false, 'permanent', 'authentication failed'),
21
- Authorization: spec('Authorization', 'GENERAL', false, 'permanent', 'authorization failed'),
22
- RateLimited: spec('RateLimited', 'GENERAL', true, 'transient', 'rate limited'),
23
- Timeout: spec('Timeout', 'GENERAL', true, 'transient', 'request timed out'),
24
- Network: spec('Network', 'GENERAL', true, 'transient', 'network error'),
25
- BackendUnavailable: spec('BackendUnavailable', 'GENERAL', true, 'transient', 'backend unavailable'),
26
- MalformedResponse: spec('MalformedResponse', 'PARSE_ERROR', false, 'permanent', 'malformed backend response'),
27
- UnsupportedCapability: spec('UnsupportedCapability', 'GENERAL', false, 'permanent', 'unsupported capability'),
28
- Configuration: spec('Configuration', 'PROVIDER_FATAL', false, 'permanent', 'invalid configuration'),
29
- AlreadyClosed: spec('AlreadyClosed', 'PROVIDER_NOT_READY', false, 'permanent', 'provider already closed'),
30
- Internal: spec('Internal', 'GENERAL', false, 'permanent', 'internal error'),
31
- });
32
- /**
33
- * The redaction contract (contracts/errors.json `rules.redaction`, start-profile
34
- * SP-26). Applied in this order: bearer tokens, URL userinfo, named
35
- * assignments, then key-shaped values. A variable NAME is never redacted on its
36
- * own; only its value is. `test/unit/redaction-contract.test.ts` runs every
37
- * contract vector through `redactSecrets`.
38
- */
39
- const REDACTION_PLACEHOLDER = '[REDACTED]';
40
- /** Variables whose assigned value is scrubbed: `NAME=value`, `NAME: value`, `NAME = "value"`. */
41
- const ASSIGNMENT_NAMES = ['FIREWEAVE_KEY', 'FIREWEAVE_BROWSER_KEY', 'FW_PROJECT_API_KEY'];
42
- /** Key families; a prefix only counts when one or more of [A-Za-z0-9_-] follows it. */
43
- const VALUE_PREFIXES = [
44
- 'project-api-key_',
45
- 'fw_public_',
46
- 'fw_ingest_pub_',
47
- 'fw_org_',
48
- 'cli_at_',
49
- 'phc_',
50
- 'phx_',
51
- 'phs_',
52
- ];
53
- const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
54
- const BEARER = /\bBearer(\s+)[A-Za-z0-9._~+/=-]+/g;
55
- // scheme://userinfo@host: userinfo cannot hold whitespace, '/', '?', '#' or '@'.
56
- const URL_USERINFO = /\b([A-Za-z][A-Za-z0-9+.-]*:\/\/)[^\s/?#@]+@/g;
57
- // The name stays, as do the separator and any opening quote; the value runs to
58
- // whitespace, a quote, a comma or a semicolon. The lookbehind keeps a longer
59
- // name that merely ends in one of these (MY_FIREWEAVE_KEY) out of scope.
60
- const ASSIGNMENT = new RegExp(`(?<![A-Za-z0-9_])(${ASSIGNMENT_NAMES.map(escapeRegExp).join('|')})(\\s*[=:]\\s*)(["']?)[^\\s"',;]+`, 'g');
61
- // No leading boundary: a key glued to other text is still a key.
62
- const KEY_VALUE = new RegExp(`(?:${VALUE_PREFIXES.map(escapeRegExp).join('|')})[A-Za-z0-9_-]+`, 'g');
63
- /**
64
- * Scrub secrets per the redaction contract, then collapse whitespace runs and
65
- * trim (so a message stays on one log line).
66
- */
67
- function redactSecrets(text) {
68
- const out = text
69
- .replace(BEARER, `Bearer$1${REDACTION_PLACEHOLDER}`)
70
- .replace(URL_USERINFO, `$1${REDACTION_PLACEHOLDER}@`)
71
- .replace(ASSIGNMENT, `$1$2$3${REDACTION_PLACEHOLDER}`)
72
- .replace(KEY_VALUE, REDACTION_PLACEHOLDER);
73
- return out.replace(/\s+/g, ' ').trim();
74
- }
75
- class FireweaveError extends Error {
76
- kind;
77
- openFeatureErrorCode;
78
- retryable;
79
- errorClass;
80
- /** Deterministic outward-facing message from the taxonomy. */
81
- safeMessage;
82
- metadata;
83
- constructor(kind, options = {}) {
84
- const taxonomy = exports.ERROR_TAXONOMY[kind];
85
- const message = options.message !== undefined ? redactSecrets(options.message) : taxonomy.defaultMessage;
86
- super(message, options.cause !== undefined ? { cause: options.cause } : undefined);
87
- this.name = 'FireweaveError';
88
- this.kind = kind;
89
- this.openFeatureErrorCode = options.openFeatureErrorCode ?? taxonomy.openFeatureErrorCode;
90
- this.retryable = taxonomy.retryable;
91
- this.errorClass = taxonomy.errorClass;
92
- this.safeMessage = taxonomy.defaultMessage;
93
- this.metadata = Object.freeze({ ...(options.metadata ?? {}) });
94
- }
95
- }
96
- exports.FireweaveError = FireweaveError;
97
- function isFireweaveError(err) {
98
- return err instanceof FireweaveError;
99
- }
@@ -1,2 +0,0 @@
1
- /** What is being registered — see spec/remote-register-target.schema.json. */
2
- export type TargetKind = 'user' | 'device';
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,107 +0,0 @@
1
- import type { FireweaveErrorKind, OpenFeatureErrorCode } from './errors.js';
2
- /** JSON-compatible value (spec/decision.schema.json `value`). */
3
- export type JsonValue = string | number | boolean | null | JsonValue[] | {
4
- [key: string]: JsonValue;
5
- };
6
- export type FlagValueType = 'boolean' | 'string' | 'number' | 'object';
7
- export type DecisionReason = 'STATIC' | 'DEFAULT' | 'TARGETING_MATCH' | 'SPLIT' | 'CACHED' | 'STALE' | 'DISABLED' | 'UNKNOWN' | 'ERROR';
8
- /** Canonical decision (spec/decision.schema.json). */
9
- export interface Decision {
10
- controlPointKey: string;
11
- value: JsonValue;
12
- reason: DecisionReason;
13
- variant?: string;
14
- errorCode?: OpenFeatureErrorCode;
15
- errorKind?: FireweaveErrorKind;
16
- errorMessage?: string;
17
- /** fireweave.* flag metadata surfaced to OpenFeature controlPointMetadata. */
18
- metadata: Record<string, string | number | boolean>;
19
- }
20
- /** Canonical evaluation context after validation/canonicalization. */
21
- export interface CanonicalContext {
22
- targetingKey?: string;
23
- /** All non-reserved attributes (targetingKey excluded). */
24
- attributes: Record<string, JsonValue>;
25
- /**
26
- * Group memberships extracted from `fireweave.groups` (canonical, ruling 13)
27
- * or the plain `groups` alias, when shaped as Record<string,string>.
28
- */
29
- groups?: Record<string, string>;
30
- /**
31
- * Group properties extracted from `fireweave.groupProperties` (canonical)
32
- * or the plain `groupProperties` alias.
33
- */
34
- groupProperties?: Record<string, JsonValue>;
35
- }
36
- export type LifecycleState = 'UNINITIALIZED' | 'INITIALIZING' | 'READY' | 'STALE' | 'ERROR' | 'FATAL' | 'SHUTDOWN';
37
- export type SignalKind = 'health' | 'error' | 'metric' | 'outcome';
38
- /** Canonical signal envelope (spec/signal.schema.json). */
39
- export interface Signal {
40
- kind: SignalKind;
41
- name: string;
42
- status?: string;
43
- errorKind?: FireweaveErrorKind;
44
- message?: string;
45
- value?: number | boolean | string;
46
- timestamp?: string;
47
- targetingKey?: string;
48
- rolloutId?: string;
49
- changeId?: string;
50
- stampId?: string;
51
- controlPointKey?: string;
52
- variant?: string;
53
- traceId?: string;
54
- role?: 'adoption' | 'guard' | 'quality' | 'custom';
55
- direction?: 'up-good' | 'up-bad' | 'neutral';
56
- attributes?: Record<string, string | number | boolean | null>;
57
- }
58
- /** Release / rollout context (spec/release-context.schema.json; ruling 15: rolloutId + stampIds required). */
59
- export interface ReleaseContext {
60
- stampIds: string[];
61
- rolloutId: string;
62
- changeId?: string;
63
- surfaces?: Array<{
64
- surfaceId: string;
65
- kind?: 'ts-server' | 'node-server' | 'python' | 'go' | 'java' | 'web' | 'other';
66
- }>;
67
- metadata?: Record<string, string | number | boolean>;
68
- }
69
- export type ReleaseStatus = 'set' | 'in_progress' | 'completed' | 'failed';
70
- export interface ReleaseState {
71
- context: ReleaseContext;
72
- status: ReleaseStatus;
73
- reason?: string;
74
- }
75
- /** Exposure event (extensions fixtures shape). */
76
- export interface Exposure {
77
- targetingKey: string;
78
- controlPointKey: string;
79
- value: JsonValue;
80
- variant?: string;
81
- rolloutId?: string;
82
- changeId?: string;
83
- stampId?: string;
84
- }
85
- /** Capability matrix (spec/capabilities.schema.json). */
86
- export interface Capabilities {
87
- static: {
88
- language: 'node';
89
- sdkVersion?: string;
90
- specVersion?: '0.1.0';
91
- openFeature: {
92
- specFloor: '0.8.0';
93
- providerName: 'fireweave';
94
- serverOnly?: boolean;
95
- };
96
- features: Record<string, boolean>;
97
- };
98
- runtime: {
99
- backend: 'fireweave' | 'inmemory' | 'none' | 'other';
100
- lifecycle: LifecycleState;
101
- features?: Record<string, boolean>;
102
- limits?: {
103
- intSafeMaxAbs?: number;
104
- shutdownTimeoutMsDefault?: number;
105
- };
106
- };
107
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,124 +0,0 @@
1
- /**
2
- * Fireweave SDK validation — pure, total functions per spec/control-points.md
3
- * "Validation, before any I/O" and spec/modes.md "Initialisation validation".
4
- *
5
- * Every read-path validator here (`validateControlPointKey`,
6
- * `validateDefaultValue`, `validateContext`, `validateTargetingKey`) returns
7
- * `Validated<T>` instead of throwing. `FireweaveRuntime.evaluate` runs them,
8
- * in the fixed order the spec names — key, default-vs-type, context,
9
- * lifecycle — and degrades to the caller's default on the first failure; it
10
- * NEVER throws (spec/control-points.md "Return discipline — never throw into
11
- * a read path").
12
- *
13
- * `validateInitOptions` is the one named exception (spec/modes.md
14
- * "Initialisation validation"): its failures are converted to a THROW by
15
- * `initFireweave` (src/init.ts). The validator itself still returns
16
- * `Validated<T>` — the entry point does the throwing, not this module.
17
- *
18
- * Collected into one module so it can move wholesale into `domain/` (plan
19
- * Phase 1.4) without touching its exports or call sites again. Everything
20
- * below is pure (no I/O, no ambient state) and total (every branch returns a
21
- * `Validated<T>`) — `conformance/` can exercise all four read-path rules
22
- * offline, with no backend.
23
- *
24
- * `validateInitOptions` is deliberately generic rather than importing
25
- * `InitFireweaveOptions` from `init.ts`: init.ts is the "mode" entry point
26
- * (Phase 1.4 assigns it to `application/`), and this module is destined for
27
- * `domain/`, which must not depend on outer layers. It also does not
28
- * validate "apiUrl fails the host allowlist" (spec/modes.md row 3) — that
29
- * check (`assertHostAllowed`) lives in `hosts.ts`, which Phase 1.4 assigns to
30
- * `infrastructure/`; it stays reachable today via `FireweaveRuntime.initialize`
31
- * (runtime.ts) / `FireweaveRemoteAdapter.initialize` (adapters/remote.ts),
32
- * unchanged by this module.
33
- */
34
- import { FireweaveError } from './errors.js';
35
- import { type ContextPolicy } from './context.js';
36
- import type { CanonicalContext, JsonValue } from './types.js';
37
- /** Result of a pure validator: success carries the validated value, failure the canonical error. */
38
- export type Validated<T> = {
39
- ok: true;
40
- value: T;
41
- } | {
42
- ok: false;
43
- error: FireweaveError;
44
- };
45
- /**
46
- * key — non-empty, ≤256 characters, no control characters
47
- * (spec/control-points.md rule 1, the first check in the fixed order).
48
- *
49
- * No taxonomy kind names "malformed key" explicitly (the return-discipline
50
- * table's closest row is "key unknown to the backend" → ControlPointNotFound): a key
51
- * that can never identify a flag is treated the same as one the backend
52
- * doesn't recognise, so this maps to ControlPointNotFound too.
53
- *
54
- * Controller-ruled interim mapping (Task 3 review): the 15-kind taxonomy in
55
- * errors.schema.json is frozen at exactly 15 entries, `InvalidContext` is
56
- * textually scoped to the evaluation *context* (not the key), and the
57
- * schema already maps another non-literal case — quota-limited responses —
58
- * onto `ControlPointNotFound` rather than adding a kind for it. `ControlPointNotFound` is
59
- * therefore the least-wrong existing kind, not a literal fit. Other-language
60
- * implementations copying node as the reference SHOULD use the same mapping
61
- * rather than each independently guessing a different one.
62
- */
63
- export declare function validateControlPointKey(key: string): Validated<string>;
64
- export type ExpectedFlagType = 'boolean' | 'string' | 'number' | 'object';
65
- /**
66
- * Whether `value` matches the shape `expected` names. Shared by
67
- * {@link validateDefaultValue} (the caller's default, before any I/O) and
68
- * `FireweaveRuntime.evaluate`'s post-resolve check (the backend's resolved
69
- * value, after I/O) — same predicate, two different inputs.
70
- */
71
- export declare function matchesExpectedType(value: JsonValue, expected: ExpectedFlagType): boolean;
72
- /**
73
- * default vs type — e.g. `getBooleanValue` with a non-boolean default is
74
- * TypeMismatch (spec/control-points.md rule 2, checked before any I/O).
75
- */
76
- export declare function validateDefaultValue(expectedType: ExpectedFlagType, defaultValue: JsonValue): Validated<JsonValue>;
77
- /**
78
- * targetingKey: "An SDK MUST NOT invent one: a missing targeting key is
79
- * InvalidContext where the evaluation needs it, never a generated anonymous
80
- * id" (spec/control-points.md "Context"). `required` is call-site policy —
81
- * the remote adapter always requires one for `resolve`/`registerTarget`
82
- * (spec/remote-protocol.md "Two identity paths"); the generic context
83
- * pipeline ({@link validateContext}) only does when
84
- * `ContextPolicy.requireTargetingKey` opts in.
85
- */
86
- export declare function validateTargetingKey(targetingKey: string | undefined, required: boolean): Validated<string | undefined>;
87
- /**
88
- * context — depth, key count, value size, reserved keys
89
- * (evaluation-context.schema.json) (spec/control-points.md rule 3). Also
90
- * enforces `policy.requireTargetingKey` via {@link validateTargetingKey}, and
91
- * — on success — extracts `groups`/`groupProperties` the same way the former
92
- * `canonicalizeContext` did.
93
- *
94
- * `merged` is the already-merged (global → client → invocation) raw input;
95
- * merging itself (`mergeContexts`) lives in context.ts and carries no
96
- * validation concerns of its own.
97
- */
98
- export declare function validateContext(merged: {
99
- targetingKey?: string;
100
- attributes: Record<string, unknown>;
101
- }, policy: ContextPolicy): Validated<CanonicalContext>;
102
- /**
103
- * Throwing wrapper around {@link validateContext} kept for the pre-existing
104
- * public surface (`FireweaveRuntime.resolveContext`, direct callers of the
105
- * package export). Read paths do not use this — they call
106
- * {@link validateContext} directly so a failure degrades instead of throwing.
107
- */
108
- export declare function canonicalizeContext(merged: {
109
- targetingKey?: string;
110
- attributes: Record<string, unknown>;
111
- }, policy: ContextPolicy): CanonicalContext;
112
- /**
113
- * Initialisation-validation table (spec/modes.md), rows 1, 2 and 4:
114
- * - `mode` absent or unrecognised
115
- * - `mode: 'remote'` with `apiKey` or `apiUrl` missing/blank
116
- * - `mode: 'local'` with credentials supplied (a config half-migrated from
117
- * remote to local reads as neither, silently — reject it instead)
118
- *
119
- * Row 3 ("apiUrl fails the host allowlist") is intentionally NOT checked
120
- * here — see the module doc comment.
121
- */
122
- export declare function validateInitOptions<T extends {
123
- readonly mode?: unknown;
124
- }>(options: T): Validated<T>;