@voltro/plugin-flags 0.86.0 → 0.87.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/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { ColumnBuilder } from '@voltro/database';
2
+ import { Context } from 'effect';
2
3
  import { DataStore } from '@voltro/database';
3
4
  import { Effect } from 'effect';
4
5
  import { FieldDefinitions } from '@voltro/database';
@@ -26,6 +27,8 @@ declare interface BufferEntry {
26
27
  lastAt: number;
27
28
  }
28
29
 
30
+ export declare const captureConfigService: (input: ConfigService) => ConfigService;
31
+
29
32
  /**
30
33
  * Check every typed flag that names an experiment against the experiments the
31
34
  * app declared. Pure — returns the problems rather than throwing, so the same
@@ -42,6 +45,94 @@ export declare const classifyShape: (value: FlagValue, now: number) => {
42
45
  readonly reason: string;
43
46
  };
44
47
 
48
+ export declare interface ConfigEntry<out A> {
49
+ readonly key: string;
50
+ readonly flag: TypedFlag<A>;
51
+ readonly public: boolean;
52
+ readonly restartRequired: 'room' | 'live';
53
+ readonly min: number | null;
54
+ readonly max: number | null;
55
+ }
56
+
57
+ /** Typed Config failures contain no private value, subject or decode body. */
58
+ export declare class ConfigError extends ConfigError_base {
59
+ }
60
+
61
+ declare const ConfigError_base: Schema.Class<ConfigError, Schema.TaggedStruct<"ConfigError", {
62
+ readonly code: Schema.Literals<readonly ["invalid_input", "invalid_value", "not_found", "unavailable"]>;
63
+ }>, YieldableError>;
64
+
65
+ declare interface ConfigKeySummary {
66
+ readonly key: string;
67
+ readonly valueType: string;
68
+ readonly public: boolean;
69
+ readonly restartRequired: 'room' | 'live';
70
+ readonly min: number | null;
71
+ readonly max: number | null;
72
+ }
73
+
74
+ export declare class ConfigPort extends ConfigPort_base {
75
+ }
76
+
77
+ declare const ConfigPort_base: Context.ServiceClass<ConfigPort, "@voltro/ConfigPort", ConfigService>;
78
+
79
+ declare interface ConfigResolutionContext {
80
+ readonly entry: ConfigEntry<unknown>;
81
+ readonly value: FlagValue;
82
+ readonly subject: FlagSubject;
83
+ readonly now: number;
84
+ }
85
+
86
+ export declare type ConfigResolver = (context: ConfigResolutionContext) => unknown;
87
+
88
+ export declare interface ConfigService {
89
+ readonly get: (key: string, subject: FlagSubject) => Effect.Effect<unknown, ConfigError>;
90
+ readonly mine: (subject: FlagSubject) => Effect.Effect<Readonly<Record<string, unknown>>, ConfigError>;
91
+ /** Snapshot outside a Room tick, then pass it through creation or app messages. */
92
+ readonly snapshot: (subject: FlagSubject, mode: 'room' | 'live') => Effect.Effect<Readonly<Record<string, unknown>>, ConfigError>;
93
+ }
94
+
95
+ export declare interface ConfigSetInput {
96
+ readonly key: string;
97
+ readonly value: unknown;
98
+ readonly actor?: string | null;
99
+ }
100
+
101
+ export declare interface ConfigSpec<S extends Schema.Top> {
102
+ readonly schema: S;
103
+ readonly default: NoInfer<Schema.Schema.Type<S>>;
104
+ readonly min?: number;
105
+ readonly max?: number;
106
+ readonly public?: boolean;
107
+ readonly restartRequired?: 'room' | 'live';
108
+ readonly variants?: DefineFlagSpec<S>['variants'];
109
+ readonly targeting?: readonly FlagTargetingRule[];
110
+ readonly rollout?: number;
111
+ readonly rolloutBy?: 'subject' | 'tenant';
112
+ readonly schedule?: FlagSchedule;
113
+ }
114
+
115
+ export declare const configSummary: (config: DefinedConfig) => readonly ConfigKeySummary[];
116
+
117
+ export declare const configSystemContract: Readonly<{
118
+ slots: {
119
+ resolver: {
120
+ defaultExport: string;
121
+ fixtureExport: string;
122
+ };
123
+ };
124
+ ports: {
125
+ config: {
126
+ tagExport: string;
127
+ fakeLayerExport: string;
128
+ fixtureExport: string;
129
+ };
130
+ };
131
+ events: readonly string[];
132
+ }>;
133
+
134
+ export declare const configValue: <Values extends Readonly<Record<string, unknown>>, Key extends keyof Values & string>(catalog: DefinedConfig<Values>, service: ConfigService, key: Key, subject: FlagSubject) => Effect.Effect<Values[Key], ConfigError>;
135
+
45
136
  /** Adapt the framework `DataStore` to a {@link FlagUsageStore}. */
46
137
  export declare const dataStoreFlagUsageStore: (store: DataStore) => FlagUsageStore;
47
138
 
@@ -50,6 +141,19 @@ export declare const dataStoreFlagUsageStore: (store: DataStore) => FlagUsageSto
50
141
  * per active flag per replica. */
51
142
  export declare const DEFAULT_FLAG_USAGE_FLUSH_MS = 300000;
52
143
 
144
+ /** Reuse Flag targeting/schedule/bucketing. Off Config always serves its default. */
145
+ export declare const defaultConfigResolver: ConfigResolver;
146
+
147
+ export declare const defineConfig: <const Schemas extends Readonly<Record<string, Schema.Top>>>(input: { readonly [Key in keyof Schemas]: ConfigSpec<Schemas[Key]>; }) => DefinedConfig<{ readonly [Key in keyof Schemas]: Schema.Schema.Type<Schemas[Key]>; }>;
148
+
149
+ export declare interface DefinedConfig<Values extends Readonly<Record<string, unknown>> = Readonly<Record<string, unknown>>> {
150
+ readonly entries: {
151
+ readonly [Key in keyof Values]: ConfigEntry<Values[Key]>;
152
+ };
153
+ readonly keys: readonly (keyof Values & string)[];
154
+ readonly typedFlags: readonly AnyTypedFlag[];
155
+ }
156
+
53
157
  /**
54
158
  * Declare a flag with a value type.
55
159
  *
@@ -194,6 +298,9 @@ export declare interface FlagAuditRow {
194
298
  readonly enabled: boolean;
195
299
  readonly previousEnabled: boolean | null;
196
300
  readonly actorId: string | null;
301
+ /** Typed Config changes only: the value set and the previous override variants. */
302
+ readonly value?: unknown;
303
+ readonly previousValue?: unknown;
197
304
  readonly at: Date;
198
305
  }
199
306
 
@@ -209,9 +316,22 @@ export declare const flagAuditTable: Table<"_voltro_feature_flag_audit", FieldDe
209
316
  readonly previousEnabled: ColumnBuilder<boolean | null, "boolean", boolean>;
210
317
  /** The acting subject id (nullable — anonymous / system flip). */
211
318
  readonly actorId: ColumnBuilder<string | null, "text", boolean>;
319
+ /** A typed Config change: the value set and the override variants it replaced (null for a flip). */
320
+ readonly value: ColumnBuilder<unknown, "json", boolean>;
321
+ readonly previousValue: ColumnBuilder<unknown, "json", boolean>;
212
322
  readonly at: ColumnBuilder<Date, "timestamp", true>;
213
323
  }>, true, "byFlagAuditFlag" | "byFlagAuditAt">;
214
324
 
325
+ /** A read facade over this plugin instance's actual merged Flag snapshot. */
326
+ export declare const flagConfigService: (input: {
327
+ readonly catalog: DefinedConfig;
328
+ readonly flags: () => Readonly<Record<string, FlagValue>>;
329
+ readonly active: () => boolean;
330
+ readonly revision: () => number;
331
+ readonly resolver?: ConfigResolver;
332
+ readonly replacement?: ConfigService;
333
+ }) => ConfigService;
334
+
215
335
  /** The result of decoding an UNTRUSTED value (a DB override, a dashboard edit)
216
336
  * against a flag's Schema. Deliberately not an exception: the caller's correct
217
337
  * response is to keep the code-declared value and say so, not to unwind. */
@@ -384,9 +504,30 @@ export declare type FlagShape =
384
504
  /** Genuinely does work: a partial rollout, targeting, variants, or a ramp. */
385
505
  | 'conditional';
386
506
 
387
- export declare const flagsPlugin: (options?: FlagsPluginOptions) => VoltroPlugin;
507
+ export declare interface FlagsPlugin extends VoltroPlugin {
508
+ readonly config?: () => ConfigService;
509
+ /** Set a typed Config value for everyone (validated against its schema, min and max): live at
510
+ * once, durable and audited with the actor and the previous variants on the postgres tier. */
511
+ readonly setConfig?: (input: ConfigSetInput) => Effect.Effect<{
512
+ readonly key: string;
513
+ readonly value: unknown;
514
+ }, ConfigError>;
515
+ /** Flip a flag's kill-switch: live at once, durable and audited (actor) on the postgres tier.
516
+ * The same path as the inspect `/toggle` endpoint; typed Config values are refused. */
517
+ readonly toggle: (input: FlagToggleInput) => Effect.Effect<FlagToggleReceipt, FlagToggleRefused>;
518
+ }
519
+
520
+ export declare const flagsPlugin: (options?: FlagsPluginOptions) => FlagsPlugin;
388
521
 
389
522
  export declare interface FlagsPluginOptions {
523
+ /** Optional typed Config, evaluated through the same Flag machinery. */
524
+ readonly config?: DefinedConfig;
525
+ readonly configVersion?: string;
526
+ readonly configResolver?: ConfigResolver;
527
+ /** Complete app-owned Config read port; no default override/policy loan. */
528
+ readonly configService?: ConfigService;
529
+ /** Full replacement invalidation sources; [] explicitly owns a static view. */
530
+ readonly configQuerySources?: readonly string[];
390
531
  /** Flags as code. The baseline; a postgres store overlays runtime toggles. */
391
532
  readonly flags?: Record<string, FlagValue>;
392
533
  /**
@@ -478,6 +619,28 @@ export declare interface FlagTargetingRule {
478
619
  readonly metadata?: Record<string, string>;
479
620
  }
480
621
 
622
+ export declare interface FlagToggleInput {
623
+ readonly key: string;
624
+ readonly enabled: boolean;
625
+ readonly actor?: string | null;
626
+ }
627
+
628
+ export declare interface FlagToggleReceipt {
629
+ readonly key: string;
630
+ readonly enabled: boolean;
631
+ readonly previous: boolean;
632
+ }
633
+
634
+ /** A refused kill-switch flip: unknown key, a typed Config value (it has its own writer),
635
+ * a store that is not bound yet, or a write whose commit could not be confirmed. */
636
+ declare class FlagToggleRefused extends FlagToggleRefused_base {
637
+ }
638
+
639
+ declare const FlagToggleRefused_base: Schema.Class<FlagToggleRefused, Schema.TaggedStruct<"FlagToggleRefused", {
640
+ readonly key: Schema.String;
641
+ readonly reason: Schema.Literals<readonly ["unknown_flag", "config_value", "not_ready", "unconfirmed"]>;
642
+ }>, YieldableError>;
643
+
481
644
  /**
482
645
  * Process-wide evaluation buffer.
483
646
  *