@supacloud/compiler 0.45.1 → 0.46.1

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/cli.js CHANGED
@@ -808,12 +808,15 @@ function validateGraph(graph, options = false) {
808
808
  if (typeof options === "object" && options.commandCapabilities) {
809
809
  const hostCaps = options.commandCapabilities;
810
810
  const rpcCaps = command.rpc && Object.hasOwn(hostCaps.rpc ?? {}, command.rpc) ? hostCaps.rpc?.[command.rpc] : undefined;
811
- if (hostCaps.requirePersistentAdapters && (command.rpc !== undefined && (!rpcCaps?.boundary || rpcCaps.audit !== true || rpcCaps.idempotency !== true) || hostCaps.permission !== true || !command.permission || !command.audit || command.idempotency !== "required" || command.rpc !== undefined && rpcCaps?.boundary === "database" && (rpcCaps.transaction !== true || command.transaction !== "required") || command.rpc === undefined && (hostCaps.audit !== true || hostCaps.idempotency !== true || hostCaps.transaction !== true || command.transaction !== "required"))) {
811
+ if (hostCaps.requirePersistentAdapters && (command.rpc !== undefined && (!rpcCaps?.boundary || rpcCaps.audit !== true || rpcCaps.idempotency !== true) || hostCaps.permission !== true || !command.permission || !command.audit || command.idempotency !== "required" || command.rpc !== undefined && rpcCaps?.boundary === "database" && (rpcCaps.transaction !== true || command.transaction !== "required") || command.rpc === undefined && (hostCaps.audit !== true || hostCaps.idempotency !== true || hostCaps.transaction !== true || command.transaction !== "required") || command.rpc !== undefined && rpcCaps?.boundary === "external" && rpcCaps.reconcile !== true)) {
812
812
  error("command-persistence-required", `Command ${command.name} requires an explicit persistent adapter, permission, audit and idempotency policy.`, module.file, module.line, "Register a named database/external adapter, enable permission checks and declare permission, audit and required idempotency on the command.");
813
813
  }
814
814
  if (rpcCaps?.boundary === "external" && (command.transaction === "required" || rpcCaps.transaction === true)) {
815
815
  error("command-external-transaction", `Command ${command.name} calls an external service; use durable intent and reconciliation, not transaction: 'required'.`, module.file, module.line, "Use transaction: 'none' with createExternalCommand; recover with read-only reconciliation. Do not claim a database transaction covers a remote request.");
816
816
  }
817
+ if (rpcCaps?.boundary === "external" && rpcCaps.reconcile !== true) {
818
+ error("command-reconcile-required", `Command ${command.name} uses an external adapter without a receipt reconciliation capability.`, module.file, module.line, "Declare reconcile: true only when the adapter can look up the same idempotency key and resolve unknown outcomes without redispatching.");
819
+ }
817
820
  const caps = command.rpc ? {
818
821
  permission: hostCaps.permission,
819
822
  audit: rpcCaps?.audit === true,
@@ -1230,6 +1233,7 @@ var init_validate = __esm(() => {
1230
1233
  "invalid-job-timeout": { code: "SC4015", docsUrl: "https://supacloud.dev/errors/SC4015" },
1231
1234
  "invalid-job-attempts": { code: "SC4016", docsUrl: "https://supacloud.dev/errors/SC4016" },
1232
1235
  "invalid-job-idempotency": { code: "SC4017", docsUrl: "https://supacloud.dev/errors/SC4017" },
1236
+ "job-retry-idempotency-required": { code: "SC4027", docsUrl: "https://supacloud.dev/errors/SC4027" },
1233
1237
  "invalid-job-mode": { code: "SC4018", docsUrl: "https://supacloud.dev/errors/SC4018" },
1234
1238
  "invalid-job-schema": { code: "SC4019", docsUrl: "https://supacloud.dev/errors/SC4019" },
1235
1239
  "command-persistence-required": { code: "SC4020", docsUrl: "https://supacloud.dev/errors/SC4020" },
@@ -1239,6 +1243,7 @@ var init_validate = __esm(() => {
1239
1243
  "command-idempotency-unsupported": { code: "SC4024", docsUrl: "https://supacloud.dev/errors/SC4024" },
1240
1244
  "command-transaction-rpc-only": { code: "SC4025", docsUrl: "https://supacloud.dev/errors/SC4025" },
1241
1245
  "command-transaction-unsupported": { code: "SC4026", docsUrl: "https://supacloud.dev/errors/SC4026" },
1246
+ "command-reconcile-required": { code: "SC4028", docsUrl: "https://supacloud.dev/errors/SC4028" },
1242
1247
  "invalid-route-contract": { code: "SC3020", docsUrl: "https://supacloud.dev/errors/SC3020" },
1243
1248
  "route-contract-required": { code: "SC3021", docsUrl: "https://supacloud.dev/errors/SC3021" },
1244
1249
  "route-contract-unverified": { code: "SC3022", docsUrl: "https://supacloud.dev/errors/SC3022" },
@@ -4592,7 +4597,7 @@ function createContextPack(graph, subject) {
4592
4597
  }
4593
4598
  }
4594
4599
  }
4595
- const modules = graph.modules.filter((module) => selected.has(module.name));
4600
+ const modules = graph.modules.filter((module) => selected.has(module.name)).map(sanitizeContextModule);
4596
4601
  const queryDocuments = graph.graphql?.documents.filter((file) => modules.some((module) => {
4597
4602
  const path = relative5(dirname4(module.file), file);
4598
4603
  return path !== ".." && !path.startsWith(`..${sep5}`);
@@ -4634,7 +4639,12 @@ function createContextPack(graph, subject) {
4634
4639
  singleResult: "async-await",
4635
4640
  eventComposition: "rxjs",
4636
4641
  angularHost: "@supacloud/app/angular",
4637
- cancellation: "explicit-owner-signal"
4642
+ cancellation: "explicit-owner-signal",
4643
+ readTransport: "postgrest-supabase-js",
4644
+ writeTransport: "command-rpc",
4645
+ writeRetry: "disabled",
4646
+ externalOutcome: "receipt-reconcile",
4647
+ databaseSource: "drizzle-append-only"
4638
4648
  },
4639
4649
  relatedModules: {
4640
4650
  imports: subjectModule.imports.filter((name) => selected.has(name)),
@@ -4642,6 +4652,44 @@ function createContextPack(graph, subject) {
4642
4652
  }
4643
4653
  };
4644
4654
  }
4655
+ function sanitizeContextModule(module) {
4656
+ const sanitizeAspect = (aspect) => ({
4657
+ ...aspect,
4658
+ expression: "[omitted]"
4659
+ });
4660
+ return {
4661
+ ...module,
4662
+ providers: module.providers.map((provider) => ({
4663
+ ...provider,
4664
+ ...provider.useValueExpr === undefined ? {} : { useValueExpr: "[omitted]" },
4665
+ ...provider.useFactoryName === undefined ? {} : { useFactoryName: "[omitted]" },
4666
+ ...provider.functionalInjects === undefined ? {} : {
4667
+ functionalInjects: provider.functionalInjects.map((inject) => ({ ...inject, expression: "[omitted]" }))
4668
+ }
4669
+ })),
4670
+ ...module.aspects === undefined ? {} : { aspects: module.aspects.map(sanitizeAspect) },
4671
+ controllers: module.controllers.map((controller) => ({
4672
+ ...controller,
4673
+ ...controller.functionalInjects === undefined ? {} : {
4674
+ functionalInjects: controller.functionalInjects.map((inject) => ({ ...inject, expression: "[omitted]" }))
4675
+ },
4676
+ routes: controller.routes.map((route) => ({
4677
+ ...route,
4678
+ ...route.aspects === undefined ? {} : { aspects: route.aspects.map(sanitizeAspect) }
4679
+ }))
4680
+ })),
4681
+ commands: module.commands.map((command) => ({
4682
+ ...command,
4683
+ ...command.aspects === undefined ? {} : { aspects: command.aspects.map(sanitizeAspect) }
4684
+ })),
4685
+ ...module.jobs === undefined ? {} : {
4686
+ jobs: module.jobs.map((job) => ({
4687
+ ...job,
4688
+ ...job.aspects === undefined ? {} : { aspects: job.aspects.map(sanitizeAspect) }
4689
+ }))
4690
+ }
4691
+ };
4692
+ }
4645
4693
  function resolveContextModule(graph, subject) {
4646
4694
  const exact = graph.modules.find((module) => module.name === subject);
4647
4695
  if (exact)
@@ -15683,6 +15731,11 @@ function parseDeliveryOptions(value) {
15683
15731
  if (value.targets?.some((target) => target.compute && target.isolation === "shared")) {
15684
15732
  throw new DeliveryConfigurationError;
15685
15733
  }
15734
+ for (const target of value.targets ?? []) {
15735
+ const invalidShape = target.kind === "function" ? target.function === undefined || target.modules !== undefined || target.compute !== undefined : target.modules === undefined || target.function !== undefined;
15736
+ if (invalidShape)
15737
+ throw new DeliveryConfigurationError;
15738
+ }
15686
15739
  const migrations = value.build?.migrations ?? [];
15687
15740
  try {
15688
15741
  validateWorkerExecution(value.execution?.groups ?? []);
@@ -15699,7 +15752,7 @@ function parseDeliveryPlanResult(value) {
15699
15752
  throw new Error("Invalid delivery plan result.");
15700
15753
  return value;
15701
15754
  }
15702
- var objectOptions, reference2, references, kind2, isolation, DeliveryFilePathSchema, DeliveryOptionsSchema, DeliveryDiagnosticSchema, routeSchema, jobSchema, DeliveryTargetSchema, DeliveryPlanSchema, DeliveryPlanResultSchema, DeliveryConfigurationError;
15755
+ var objectOptions, reference2, references, kind2, isolation, DeliveryFilePathSchema, functionTarget, DeliveryOptionsSchema, DeliveryDiagnosticSchema, routeSchema, jobSchema, DeliveryTargetSchema, DeliveryPlanSchema, DeliveryPlanResultSchema, DeliveryConfigurationError;
15703
15756
  var init_delivery_schema = __esm(() => {
15704
15757
  init_build();
15705
15758
  init_value2();
@@ -15707,22 +15760,28 @@ var init_delivery_schema = __esm(() => {
15707
15760
  objectOptions = { additionalProperties: false };
15708
15761
  reference2 = String2({ minLength: 1, maxLength: 128, pattern: "^[A-Za-z][A-Za-z0-9_.:/-]*$" });
15709
15762
  references = _Array_(reference2, { uniqueItems: true });
15710
- kind2 = Union([Literal("api"), Literal("jobs"), Literal("webhook")]);
15763
+ kind2 = Union([Literal("api"), Literal("jobs"), Literal("webhook"), Literal("function")]);
15711
15764
  isolation = Union([Literal("shared"), Literal("process")]);
15712
15765
  DeliveryFilePathSchema = String2({
15713
15766
  maxLength: 512,
15714
15767
  pattern: "^(?:[A-Za-z0-9_-][A-Za-z0-9_.-]*/)*[A-Za-z0-9_-][A-Za-z0-9_.-]*$"
15715
15768
  });
15769
+ functionTarget = _Object_({
15770
+ slug: String2({ pattern: "^[a-z][a-z0-9-]{0,62}$" }),
15771
+ entrypoint: DeliveryFilePathSchema,
15772
+ verifyJwt: Boolean2()
15773
+ }, objectOptions);
15716
15774
  DeliveryOptionsSchema = _Object_({
15717
15775
  version: Literal(1),
15718
15776
  execution: Optional(WorkerExecutionSchema),
15719
15777
  targets: Optional(_Array_(_Object_({
15720
15778
  name: String2({ pattern: "^[a-z][a-z0-9-]{0,62}$" }),
15721
15779
  kind: kind2,
15722
- modules: _Array_(reference2, { minItems: 1, uniqueItems: true }),
15780
+ modules: Optional(_Array_(reference2, { minItems: 1, uniqueItems: true })),
15723
15781
  isolation: Optional(isolation),
15724
15782
  capabilities: Optional(references),
15725
- compute: Optional(ComputeResourcesSchema)
15783
+ compute: Optional(ComputeResourcesSchema),
15784
+ function: Optional(functionTarget)
15726
15785
  }, objectOptions))),
15727
15786
  runtime: Optional(_Object_({
15728
15787
  processIsolation: Boolean2(),
@@ -15800,6 +15859,7 @@ var init_delivery_schema = __esm(() => {
15800
15859
  routes: _Array_(routeSchema),
15801
15860
  jobs: _Array_(jobSchema),
15802
15861
  externalTokens: _Array_(String2()),
15862
+ function: Optional(functionTarget),
15803
15863
  requirements: _Object_({
15804
15864
  processIsolation: Boolean2(),
15805
15865
  durableQueue: Boolean2(),
@@ -16976,8 +17036,172 @@ var init_deployment_evidence = __esm(() => {
16976
17036
  }, closed8);
16977
17037
  });
16978
17038
 
17039
+ // node_modules/@supacloud/delivery/src/delivery-tuple.ts
17040
+ var sha2563, commit, isoDate2, DELIVERY_TUPLE_SCHEMA = "supacloud.fa-delivery-tuple.v1", FaDeliveryTupleSchema;
17041
+ var init_delivery_tuple = __esm(() => {
17042
+ init_build();
17043
+ init_value2();
17044
+ sha2563 = String2({ pattern: "^[a-f0-9]{64}$" });
17045
+ commit = String2({ pattern: "^(?:[a-f0-9]{40}|[a-f0-9]{64})$" });
17046
+ isoDate2 = String2({ minLength: 20, maxLength: 40 });
17047
+ FaDeliveryTupleSchema = _Object_({
17048
+ schema: Literal(DELIVERY_TUPLE_SCHEMA),
17049
+ customer: Literal("xigu-fa"),
17050
+ fa_commit: commit,
17051
+ cli: _Object_({
17052
+ version: String2({ pattern: "^\\d+\\.\\d+\\.\\d+$" })
17053
+ }, { additionalProperties: false }),
17054
+ platform_commit: commit,
17055
+ edge_runtime: _Object_({
17056
+ version: String2({ minLength: 1, maxLength: 128 }),
17057
+ artifact_sha256: sha2563
17058
+ }, { additionalProperties: false }),
17059
+ compatibility_window: _Object_({
17060
+ contract_schema: String2({ minLength: 1, maxLength: 128 }),
17061
+ starts_at: isoDate2,
17062
+ ends_at: isoDate2,
17063
+ old_client_supported: Boolean2(),
17064
+ partial_deployment_supported: Boolean2()
17065
+ }, { additionalProperties: false })
17066
+ }, { additionalProperties: false });
17067
+ });
17068
+
17069
+ // node_modules/@supacloud/delivery/src/contract-matrix.ts
17070
+ var closed9, sha2564, generation, versions, CONTRACT_MATRIX_SCHEMA = "supacloud.consumer-contract-matrix.v1", FA_CONTRACT_SCENARIOS, ConsumerContractMatrixSchema;
17071
+ var init_contract_matrix = __esm(() => {
17072
+ init_build();
17073
+ init_value2();
17074
+ closed9 = { additionalProperties: false };
17075
+ sha2564 = String2({ pattern: "^[a-f0-9]{64}$" });
17076
+ generation = Union([Literal("old"), Literal("new")]);
17077
+ versions = _Object_({ old: sha2564, new: sha2564 }, closed9);
17078
+ FA_CONTRACT_SCENARIOS = [
17079
+ "missing-display-field",
17080
+ "missing-authority-field",
17081
+ "added-field",
17082
+ "legacy-envelope",
17083
+ "lost-write-response",
17084
+ "downgrade"
17085
+ ];
17086
+ ConsumerContractMatrixSchema = _Object_({
17087
+ schema: Literal(CONTRACT_MATRIX_SCHEMA),
17088
+ customer: Literal("xigu-fa"),
17089
+ baseline_tuple_sha256: sha2564,
17090
+ candidate_tuple_sha256: sha2564,
17091
+ artifacts: _Object_({ frontend: versions, functions: versions, database: versions }, closed9),
17092
+ cases: _Array_(_Object_({
17093
+ frontend: generation,
17094
+ functions: generation,
17095
+ database: generation,
17096
+ scenarios: _Array_(_Object_({
17097
+ name: Enum(FA_CONTRACT_SCENARIOS),
17098
+ expected: Union([Literal("compatible"), Literal("blocked-safely")])
17099
+ }, closed9), { minItems: FA_CONTRACT_SCENARIOS.length, maxItems: FA_CONTRACT_SCENARIOS.length })
17100
+ }, closed9), { minItems: 8, maxItems: 8 })
17101
+ }, closed9);
17102
+ });
17103
+
17104
+ // node_modules/@supacloud/delivery/src/fa-stability.ts
17105
+ var closed10, hash3, label, timestamp2, count2, environment2, FA_REQUIRED_ACCEPTANCE, FA_BUSINESS_OPERATIONS, operation, proof, FaBusinessObservationSchema, FaServiceObjectivesSchema, FaStabilityEvidenceSchema;
17106
+ var init_fa_stability = __esm(() => {
17107
+ init_build();
17108
+ init_value2();
17109
+ init_delivery_files();
17110
+ init_contract_matrix();
17111
+ init_delivery_tuple();
17112
+ closed10 = { additionalProperties: false };
17113
+ hash3 = String2({ pattern: "^[a-f0-9]{64}$" });
17114
+ label = String2({ minLength: 1, maxLength: 256, pattern: "\\S" });
17115
+ timestamp2 = String2({ minLength: 24, maxLength: 24 });
17116
+ count2 = Integer({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER });
17117
+ environment2 = Union([Literal("test"), Literal("production")]);
17118
+ FA_REQUIRED_ACCEPTANCE = {
17119
+ login: "real-browser",
17120
+ permissions: "real-http",
17121
+ upload: "real-http",
17122
+ "async-task": "real-worker",
17123
+ deploy: "real-http",
17124
+ "database-migration": "real-database",
17125
+ schedule: "real-worker",
17126
+ rollback: "real-drill",
17127
+ "error-policy": "real-http",
17128
+ "alert-delivery": "real-drill"
17129
+ };
17130
+ FA_BUSINESS_OPERATIONS = ["login", "permissions", "upload", "async-task", "report", "deploy"];
17131
+ operation = Enum(FA_BUSINESS_OPERATIONS);
17132
+ proof = _Object_({
17133
+ path: String2({ pattern: "^[A-Za-z0-9_-][A-Za-z0-9_./-]{0,255}$" }),
17134
+ sha256: hash3
17135
+ }, closed10);
17136
+ FaBusinessObservationSchema = _Object_({
17137
+ id: String2({ pattern: "^[A-Za-z0-9_-]{1,128}$" }),
17138
+ tuple_sha256: hash3,
17139
+ operation,
17140
+ started_at: timestamp2,
17141
+ finished_at: timestamp2,
17142
+ outcome: Enum(["success", "failure", "timeout", "unknown"]),
17143
+ attempts: Integer({ minimum: 1, maximum: 1000 }),
17144
+ rollbacks: count2
17145
+ }, closed10);
17146
+ FaServiceObjectivesSchema = _Object_({
17147
+ status: Literal("approved"),
17148
+ owner: label,
17149
+ approval_reference: label,
17150
+ approved_at: timestamp2,
17151
+ project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
17152
+ environment: environment2,
17153
+ alert_route: label,
17154
+ window_hours: Number2({ exclusiveMinimum: 0, maximum: 8760 }),
17155
+ max_evidence_age_hours: Number2({ exclusiveMinimum: 0, maximum: 168 }),
17156
+ operations: _Array_(_Object_({
17157
+ operation,
17158
+ minimum_samples: Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER }),
17159
+ availability_percent: Number2({ exclusiveMinimum: 0, maximum: 100 }),
17160
+ p95_ms: Number2({ exclusiveMinimum: 0, maximum: Number.MAX_SAFE_INTEGER })
17161
+ }, closed10), { minItems: FA_BUSINESS_OPERATIONS.length, maxItems: FA_BUSINESS_OPERATIONS.length })
17162
+ }, closed10);
17163
+ FaStabilityEvidenceSchema = _Object_({
17164
+ schema: Literal("supacloud.fa-stability-evidence.v1"),
17165
+ environment: environment2,
17166
+ project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
17167
+ tuple_sha256: hash3,
17168
+ matrix_sha256: hash3,
17169
+ objectives_sha256: hash3,
17170
+ recorded_at: timestamp2,
17171
+ window_start: timestamp2,
17172
+ window_end: timestamp2,
17173
+ reviewed_by: label,
17174
+ review_reference: label,
17175
+ acceptance: _Array_(_Object_({
17176
+ id: Enum(Object.keys(FA_REQUIRED_ACCEPTANCE)),
17177
+ execution: Enum([
17178
+ "real-browser",
17179
+ "real-http",
17180
+ "real-worker",
17181
+ "real-database",
17182
+ "real-drill",
17183
+ "local-fake"
17184
+ ]),
17185
+ passed: Boolean2(),
17186
+ measured_at: timestamp2,
17187
+ proof
17188
+ }, closed10), { minItems: 10, maxItems: 10 }),
17189
+ matrix: _Array_(_Object_({
17190
+ combination: label,
17191
+ scenario: label,
17192
+ outcome: Union([Literal("compatible"), Literal("blocked-safely")]),
17193
+ execution: Union([Literal("real-http-and-database"), Literal("local-fake")]),
17194
+ passed: Boolean2(),
17195
+ measured_at: timestamp2,
17196
+ proof
17197
+ }, closed10), { minItems: 48, maxItems: 48 }),
17198
+ observation: proof,
17199
+ alert: _Object_({ route: label, acknowledged_by: label, delivered_at: timestamp2 }, closed10)
17200
+ }, closed10);
17201
+ });
17202
+
16979
17203
  // node_modules/@supacloud/delivery/src/application-promotion.ts
16980
- var closed9, projectRef2, sha2563, nullableActivation2, nullableDigest, observation, blocker, ApplicationPromotionPlanSchema;
17204
+ var closed11, projectRef2, sha2565, nullableActivation2, nullableDigest, observation, blocker, ApplicationPromotionPlanSchema;
16981
17205
  var init_application_promotion = __esm(() => {
16982
17206
  init_build();
16983
17207
  init_value2();
@@ -16985,11 +17209,11 @@ var init_application_promotion = __esm(() => {
16985
17209
  init_application_activation();
16986
17210
  init_application_configuration();
16987
17211
  init_application_release();
16988
- closed9 = { additionalProperties: false };
17212
+ closed11 = { additionalProperties: false };
16989
17213
  projectRef2 = String2({ pattern: "^[a-z0-9-]{1,20}$" });
16990
- sha2563 = ApplicationReleaseIdSchema;
17214
+ sha2565 = ApplicationReleaseIdSchema;
16991
17215
  nullableActivation2 = Union([ApplicationActivationIdSchema, Null()]);
16992
- nullableDigest = Union([sha2563, Null()]);
17216
+ nullableDigest = Union([sha2565, Null()]);
16993
17217
  observation = {
16994
17218
  activation_id: nullableActivation2,
16995
17219
  receipt_confirmed: Boolean2(),
@@ -17015,33 +17239,33 @@ var init_application_promotion = __esm(() => {
17015
17239
  project_ref: projectRef2,
17016
17240
  application_id: ApplicationIdSchema,
17017
17241
  environment_id: ApplicationIdSchema,
17018
- manifest_sha256: sha2563,
17019
- plan_sha256: sha2563,
17242
+ manifest_sha256: sha2565,
17243
+ plan_sha256: sha2565,
17020
17244
  source: _Object_({
17021
17245
  project_ref: projectRef2,
17022
17246
  environment_id: ApplicationIdSchema,
17023
- release_id: sha2563,
17247
+ release_id: sha2565,
17024
17248
  ...observation
17025
- }, closed9),
17249
+ }, closed11),
17026
17250
  target: _Object_({
17027
- candidate_release_id: sha2563,
17028
- current_release_id: Union([sha2563, Null()]),
17251
+ candidate_release_id: sha2565,
17252
+ current_release_id: Union([sha2565, Null()]),
17029
17253
  artifact_action: Union([Literal("materialize"), Literal("reuse")]),
17030
17254
  configuration_id: Union([ApplicationConfigurationIdSchema, Null()]),
17031
17255
  configuration: Union([ApplicationConfigurationViewSchema, Null()]),
17032
17256
  ...observation
17033
- }, closed9),
17257
+ }, closed11),
17034
17258
  migrations: _Object_({
17035
- ledger_digest: sha2563,
17259
+ ledger_digest: sha2565,
17036
17260
  ledger_compatible: Boolean2(),
17037
17261
  project_migrations_applied: Boolean2(),
17038
17262
  pending_versions: _Array_(String2({ pattern: "^\\d{1,20}$" }), { maxItems: 4096, uniqueItems: true }),
17039
17263
  operator_provisioning_required: Boolean2()
17040
- }, closed9),
17264
+ }, closed11),
17041
17265
  backup: _Object_({
17042
17266
  required: Boolean2(),
17043
17267
  confirmed: Literal(false)
17044
- }, closed9),
17268
+ }, closed11),
17045
17269
  action: Union([Literal("promote"), Literal("no-op"), Literal("blocked")]),
17046
17270
  blockers: _Array_(Enum([...blocker]), {
17047
17271
  maxItems: blocker.length,
@@ -17050,7 +17274,7 @@ var init_application_promotion = __esm(() => {
17050
17274
  steps: _Array_(String2({ minLength: 1, maxLength: 64 }), { maxItems: 8, uniqueItems: true }),
17051
17275
  execution_performed: Literal(false),
17052
17276
  data_recovery: Literal("separate-required")
17053
- }, closed9);
17277
+ }, closed11);
17054
17278
  });
17055
17279
 
17056
17280
  // node_modules/@supacloud/delivery/src/application-runtime-identity.ts
@@ -17182,6 +17406,9 @@ var init_src = __esm(() => {
17182
17406
  init_application_release_transfer();
17183
17407
  init_application_configuration();
17184
17408
  init_deployment_evidence();
17409
+ init_delivery_tuple();
17410
+ init_contract_matrix();
17411
+ init_fa_stability();
17185
17412
  init_application_promotion();
17186
17413
  init_application_runtime_identity();
17187
17414
  init_delivery_build_schema();
@@ -17345,7 +17572,7 @@ import { createHash as createHash12 } from "node:crypto";
17345
17572
  import { mkdir as mkdir5, readFile as readFile13 } from "node:fs/promises";
17346
17573
  import { dirname as dirname11, relative as relative12, resolve as resolve24 } from "node:path";
17347
17574
  import * as ts18 from "@typescript/typescript6";
17348
- function hash3(value) {
17575
+ function hash4(value) {
17349
17576
  return createHash12("sha256").update(value).digest("hex");
17350
17577
  }
17351
17578
  function importPath(out, path) {
@@ -17411,7 +17638,7 @@ async function generateDatabaseContracts(options, check = false) {
17411
17638
  const inputs = {};
17412
17639
  const addInput = async (path) => {
17413
17640
  const absolute = resolve24(rootDir, path);
17414
- inputs[relative12(rootDir, absolute).replaceAll("\\", "/")] = hash3(await readFile13(absolute, "utf8"));
17641
+ inputs[relative12(rootDir, absolute).replaceAll("\\", "/")] = hash4(await readFile13(absolute, "utf8"));
17415
17642
  };
17416
17643
  await addInput(postgrestTypes);
17417
17644
  await addInput(drizzleSchema);
@@ -17450,7 +17677,7 @@ async function generateDatabaseContracts(options, check = false) {
17450
17677
  role: options.role,
17451
17678
  inputs: Object.fromEntries(Object.entries(inputs).sort(([a], [b]) => a.localeCompare(b))),
17452
17679
  migrationOrder: options.migrations.map((path) => relative12(rootDir, resolve24(rootDir, path)).replaceAll("\\", "/")),
17453
- outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash3(text)]))
17680
+ outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash4(text)]))
17454
17681
  };
17455
17682
  files["database.manifest.json"] = JSON.stringify(manifest, null, 2) + `
17456
17683
  `;
@@ -21143,9 +21370,25 @@ import * as ts9 from "@typescript/typescript6";
21143
21370
  var SOURCE_SEMANTIC_DIAGNOSTIC_CODES = {
21144
21371
  "source-unsafe-any": { errorCode: "SC6009", docsUrl: "https://supacloud.dev/errors/SC6009" },
21145
21372
  "source-floating-promise": { errorCode: "SC6010", docsUrl: "https://supacloud.dev/errors/SC6010" },
21146
- "source-non-exhaustive-switch": { errorCode: "SC6011", docsUrl: "https://supacloud.dev/errors/SC6011" }
21373
+ "source-non-exhaustive-switch": { errorCode: "SC6011", docsUrl: "https://supacloud.dev/errors/SC6011" },
21374
+ "source-alternative-library": { errorCode: "SC6012", docsUrl: "https://supacloud.dev/errors/SC6012" }
21147
21375
  };
21148
- function scanSourceSemantics(source, checker, file, rootDir) {
21376
+ var DEFAULT_ALTERNATIVE_LIBRARIES = [
21377
+ "@apollo/client",
21378
+ "@urql/core",
21379
+ "graphql-request",
21380
+ "kefir",
21381
+ "most",
21382
+ "@pgflow",
21383
+ "pgflow",
21384
+ "pg_durable",
21385
+ "react-relay",
21386
+ "redux-observable",
21387
+ "urql",
21388
+ "wonka",
21389
+ "xstream"
21390
+ ];
21391
+ function scanSourceSemantics(source, checker, file, rootDir, options = {}) {
21149
21392
  const diagnostics = [];
21150
21393
  const report = (code, node, message) => {
21151
21394
  diagnostics.push({
@@ -21157,6 +21400,16 @@ function scanSourceSemantics(source, checker, file, rootDir) {
21157
21400
  line: source.getLineAndCharacterOfPosition(node.getStart(source)).line + 1
21158
21401
  });
21159
21402
  };
21403
+ const allowedLibraries = new Set(options.allowAlternativeLibraries ?? []);
21404
+ for (const statement of source.statements) {
21405
+ if (!ts9.isImportDeclaration(statement) || !ts9.isStringLiteral(statement.moduleSpecifier))
21406
+ continue;
21407
+ const moduleName = statement.moduleSpecifier.text;
21408
+ const alternative = DEFAULT_ALTERNATIVE_LIBRARIES.find((name) => moduleName === name || moduleName.startsWith(`${name}/`));
21409
+ if (alternative && !allowedLibraries.has(alternative) && !allowedLibraries.has(moduleName)) {
21410
+ report("source-alternative-library", statement.moduleSpecifier, `Production source imports alternative library "${moduleName}". Use the governed Supabase client/PostgREST transport and RxJS event composition by default, or allow this package explicitly in typeSafety.allowAlternativeLibraries for a documented boundary.`);
21411
+ }
21412
+ }
21160
21413
  const unsafe = (value, target) => {
21161
21414
  if (isUnknownBoundary(target, checker) || containsAny(target, checker, new Set, rootDir))
21162
21415
  return;
@@ -21437,7 +21690,7 @@ function scanProductionSource(options) {
21437
21690
  }
21438
21691
  for (const sourceFile of sourceFiles) {
21439
21692
  scanSourceFile(sourceFile, checker, rootDir, diagnostics, options.strict ?? false);
21440
- diagnostics.push(...scanSourceSemantics(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), rootDir));
21693
+ diagnostics.push(...scanSourceSemantics(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), rootDir, options.allowAlternativeLibraries === undefined ? {} : { allowAlternativeLibraries: options.allowAlternativeLibraries }));
21441
21694
  diagnostics.push(...scanDrizzleSql(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), options.strict ?? false));
21442
21695
  const scanner = ts10.createScanner(ts10.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
21443
21696
  for (let kind = scanner.scan();kind !== ts10.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
@@ -21699,6 +21952,17 @@ function validateEffectPolicies(graph, options = {}) {
21699
21952
  }
21700
21953
  return diagnostics;
21701
21954
  }
21955
+ function validateJobPolicies(graph) {
21956
+ const diagnostics = [];
21957
+ for (const module of graph.modules) {
21958
+ for (const job of module.jobs ?? []) {
21959
+ if (job.maxAttempts !== undefined && job.maxAttempts > 1 && job.idempotency !== "required") {
21960
+ diagnostics.push(diagnostic("job-retry-idempotency-required", `Job ${job.name} (${job.className}) enables ${job.maxAttempts} attempts without an idempotency contract.`, module.file, 'Use idempotency: "required" with a durable receipt, or set maxAttempts: 1.'));
21961
+ }
21962
+ }
21963
+ }
21964
+ return diagnostics;
21965
+ }
21702
21966
 
21703
21967
  // src/database-governance.ts
21704
21968
  import { execFile } from "node:child_process";
@@ -21748,13 +22012,19 @@ async function checkDatabaseGovernance(rootDir, value) {
21748
22012
 
21749
22013
  // src/compile.ts
21750
22014
  function withDefaultGovernance(options) {
21751
- return options.commandCapabilities === undefined ? { ...options, commandCapabilities: {
21752
- requirePersistentAdapters: true,
21753
- permission: true,
21754
- audit: true,
21755
- idempotency: true,
21756
- transaction: true
21757
- } } : options;
22015
+ return {
22016
+ ...options,
22017
+ requireRouteContracts: options.requireRouteContracts ?? true,
22018
+ disallowControllerDirectDb: options.disallowControllerDirectDb ?? true,
22019
+ detectOrphanModules: options.detectOrphanModules ?? true,
22020
+ ...options.commandCapabilities === undefined ? { commandCapabilities: {
22021
+ requirePersistentAdapters: true,
22022
+ permission: true,
22023
+ audit: true,
22024
+ idempotency: true,
22025
+ transaction: true
22026
+ } } : {}
22027
+ };
21758
22028
  }
21759
22029
  async function renderOptionalGraphql(options) {
21760
22030
  return options.graphql ? (await Promise.resolve().then(() => (init_graphql(), exports_graphql))).renderGraphql(options) : { diagnostics: [], files: {} };
@@ -21766,7 +22036,8 @@ async function compileProject(options) {
21766
22036
  ...graph.diagnostics ?? [],
21767
22037
  ...validateGraph(graph, options),
21768
22038
  ...validateClientSchemaBoundaries(graph, options),
21769
- ...validateEffectPolicies(graph, options.effect)
22039
+ ...validateEffectPolicies(graph, options.effect),
22040
+ ...validateJobPolicies(graph)
21770
22041
  ];
21771
22042
  const databaseDiagnostics = await checkDatabaseGovernance(options.rootDir, options.databaseGovernance);
21772
22043
  diagnostics.push(...databaseDiagnostics);
@@ -21836,7 +22107,8 @@ async function checkProject(options) {
21836
22107
  ...graph.diagnostics ?? [],
21837
22108
  ...validateGraph(graph, options),
21838
22109
  ...validateClientSchemaBoundaries(graph, options),
21839
- ...validateEffectPolicies(graph, options.effect)
22110
+ ...validateEffectPolicies(graph, options.effect),
22111
+ ...validateJobPolicies(graph)
21840
22112
  ];
21841
22113
  const databaseDiagnostics = await checkDatabaseGovernance(options.rootDir, options.databaseGovernance);
21842
22114
  diagnostics.push(...databaseDiagnostics);
@@ -21916,7 +22188,8 @@ function resolveTypeSafety(options) {
21916
22188
  return {
21917
22189
  noAnyInGenerated: true,
21918
22190
  scanProductionSource: true,
21919
- ...options.typeSafety?.exclude ? { exclude: options.typeSafety.exclude } : {}
22191
+ ...options.typeSafety?.exclude ? { exclude: options.typeSafety.exclude } : {},
22192
+ ...options.typeSafety?.allowAlternativeLibraries ? { allowAlternativeLibraries: options.typeSafety.allowAlternativeLibraries } : {}
21920
22193
  };
21921
22194
  }
21922
22195
 
@@ -22650,11 +22923,13 @@ var DEFAULT_SUPACLOUD_CONFIG = {
22650
22923
  outDir: "generated",
22651
22924
  include: ["**/*.module.ts", "**/*.ts"],
22652
22925
  strict: true,
22653
- requireRouteContracts: false,
22926
+ requireRouteContracts: true,
22654
22927
  generateClient: true,
22655
22928
  generateOpenApi: true,
22656
22929
  generatePermissions: true,
22657
22930
  treeShakeUnusedProviders: true,
22931
+ disallowControllerDirectDb: true,
22932
+ detectOrphanModules: true,
22658
22933
  commandCapabilities: {
22659
22934
  requirePersistentAdapters: true,
22660
22935
  permission: true,
@@ -22709,9 +22984,9 @@ function validateGovernanceConfig(config) {
22709
22984
  if (!isRecord(adapters))
22710
22985
  throw new Error("commandCapabilities.rpc must contain named adapters.");
22711
22986
  for (const [name, adapter] of Object.entries(adapters)) {
22712
- if (!name.trim() || !isRecord(adapter) || Object.keys(adapter).some((key) => !["audit", "idempotency", "transaction", "boundary"].includes(key)))
22987
+ if (!name.trim() || !isRecord(adapter) || Object.keys(adapter).some((key) => !["audit", "idempotency", "reconcile", "transaction", "boundary"].includes(key)))
22713
22988
  throw new Error("Invalid command adapter.");
22714
- for (const key of ["audit", "idempotency", "transaction"]) {
22989
+ for (const key of ["audit", "idempotency", "reconcile", "transaction"]) {
22715
22990
  if (adapter[key] !== undefined && typeof adapter[key] !== "boolean")
22716
22991
  throw new Error("Invalid command adapter capability.");
22717
22992
  }
@@ -22736,8 +23011,8 @@ function validateGovernanceConfig(config) {
22736
23011
  }
22737
23012
  if (config.typeSafety !== undefined) {
22738
23013
  const rules = config.typeSafety;
22739
- if (!isRecord(rules) || Object.keys(rules).some((key) => !["scanProductionSource", "noAnyInGenerated", "exclude"].includes(key)) || rules["scanProductionSource"] !== undefined && typeof rules["scanProductionSource"] !== "boolean" || rules["noAnyInGenerated"] !== undefined && typeof rules["noAnyInGenerated"] !== "boolean" || rules["exclude"] !== undefined && !isStrings(rules["exclude"])) {
22740
- throw new Error("typeSafety accepts boolean scanProductionSource/noAnyInGenerated and a string array exclude.");
23014
+ if (!isRecord(rules) || Object.keys(rules).some((key) => !["scanProductionSource", "noAnyInGenerated", "exclude", "allowAlternativeLibraries"].includes(key)) || rules["scanProductionSource"] !== undefined && typeof rules["scanProductionSource"] !== "boolean" || rules["noAnyInGenerated"] !== undefined && typeof rules["noAnyInGenerated"] !== "boolean" || rules["exclude"] !== undefined && !isStrings(rules["exclude"]) || rules["allowAlternativeLibraries"] !== undefined && !isStrings(rules["allowAlternativeLibraries"])) {
23015
+ throw new Error("typeSafety accepts boolean scanProductionSource/noAnyInGenerated and string arrays exclude/allowAlternativeLibraries.");
22741
23016
  }
22742
23017
  }
22743
23018
  for (const key of ["allowRouteCommandBindings", "disallowControllerDirectDb", "detectOrphanModules"]) {
@@ -22796,8 +23071,8 @@ function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
22796
23071
  }
22797
23072
  },
22798
23073
  ...resolved.allowRouteCommandBindings === undefined ? {} : { allowRouteCommandBindings: resolved.allowRouteCommandBindings },
22799
- ...resolved.disallowControllerDirectDb === undefined ? {} : { disallowControllerDirectDb: resolved.disallowControllerDirectDb },
22800
- ...resolved.detectOrphanModules === undefined ? {} : { detectOrphanModules: resolved.detectOrphanModules },
23074
+ disallowControllerDirectDb: resolved.disallowControllerDirectDb ?? DEFAULT_SUPACLOUD_CONFIG.disallowControllerDirectDb,
23075
+ detectOrphanModules: resolved.detectOrphanModules ?? DEFAULT_SUPACLOUD_CONFIG.detectOrphanModules,
22801
23076
  effect: resolved.effect === undefined ? { ...DEFAULT_SUPACLOUD_CONFIG.effect } : { ...DEFAULT_SUPACLOUD_CONFIG.effect, ...resolved.effect },
22802
23077
  treeShakeUnusedProviders: resolved.treeShakeUnusedProviders ?? DEFAULT_SUPACLOUD_CONFIG.treeShakeUnusedProviders,
22803
23078
  ...resolved.graphql === undefined || resolved.graphql === false ? {} : { graphql: {
@@ -22931,7 +23206,7 @@ function createDeliveryPlan(graph, input, validation) {
22931
23206
  if (target.name === "api" && target.kind !== "api" || target.name === "jobs" && target.kind !== "jobs") {
22932
23207
  fail("delivery-reserved-target", `"${target.name}" is reserved for its matching workload kind.`, "Rename the target or use the matching kind.");
22933
23208
  }
22934
- for (const name of sorted(target.modules)) {
23209
+ for (const name of sorted(target.modules ?? [])) {
22935
23210
  if (!modules.has(name)) {
22936
23211
  fail("delivery-unknown-module", `Target "${target.name}" refers to unknown module "${name}".`, "Select a module name from the compiler graph.");
22937
23212
  continue;
@@ -22945,6 +23220,23 @@ function createDeliveryPlan(graph, input, validation) {
22945
23220
  }
22946
23221
  }
22947
23222
  const targets = new Map;
23223
+ for (const declaration of declarations.values()) {
23224
+ if (declaration.kind !== "function" || declaration.function === undefined)
23225
+ continue;
23226
+ targets.set(declaration.name, {
23227
+ name: declaration.name,
23228
+ kind: "function",
23229
+ isolation: "shared",
23230
+ roots: [],
23231
+ modules: [],
23232
+ routes: [],
23233
+ jobs: [],
23234
+ externalTokens: [],
23235
+ function: declaration.function,
23236
+ requirements: { processIsolation: false, durableQueue: false, capabilities: sorted(declaration.capabilities ?? []) },
23237
+ runtimeStatus: options.runtime === undefined ? "unchecked" : "declared-compatible"
23238
+ });
23239
+ }
22948
23240
  function getTarget(name, fallback) {
22949
23241
  const existing = targets.get(name);
22950
23242
  if (existing)
@@ -23814,6 +24106,14 @@ async function buildDeliveryProject(options, delivery) {
23814
24106
  const planned = createDeliveryPlan({ ...checked.graph, diagnostics: checked.diagnostics }, settings, options);
23815
24107
  if (!planned.ok)
23816
24108
  return failed(planned.diagnostics);
24109
+ if (planned.plan.targets.some((target) => target.kind === "function")) {
24110
+ return failed([{
24111
+ severity: "error",
24112
+ code: "delivery-function-build-unsupported",
24113
+ message: "Function target rendering is not implemented yet; the delivery build only produces HTTP and Worker application objects.",
24114
+ suggestion: "Declare HTTP/Worker application targets for now; Function and schedule delivery is tracked separately."
24115
+ }]);
24116
+ }
23817
24117
  if (options.graphql && checked.mismatches.some((mismatch) => mismatch.startsWith("graphql"))) {
23818
24118
  throw new Error("Refresh GraphQL artifacts with compile before building independent targets.");
23819
24119
  }
@@ -24083,10 +24383,10 @@ import { readFileSync as readFileSync4 } from "node:fs";
24083
24383
  import { resolve as resolve18 } from "node:path";
24084
24384
 
24085
24385
  // src/migration-app-version.ts
24086
- var MIGRATION_APP_VERSION = "0.26.1";
24386
+ var MIGRATION_APP_VERSION = "0.27.0";
24087
24387
 
24088
24388
  // src/migration-elysia-version.ts
24089
- var MIGRATION_ELYSIA_VERSION = "0.29.2";
24389
+ var MIGRATION_ELYSIA_VERSION = "0.30.0";
24090
24390
 
24091
24391
  // src/migration-policy.ts
24092
24392
  var cachedCompilerVersion;
@@ -25056,7 +25356,7 @@ function isRecord2(value) {
25056
25356
  function arrayLength(value) {
25057
25357
  return Array.isArray(value) ? value.length : undefined;
25058
25358
  }
25059
- async function sha2564(path) {
25359
+ async function sha2566(path) {
25060
25360
  return createHash11("sha256").update(await readFile11(path)).digest("hex");
25061
25361
  }
25062
25362
  function overallStatus(findings) {
@@ -25133,7 +25433,7 @@ async function assessMigration(options) {
25133
25433
  contractsManifest = {
25134
25434
  path: contractsManifestPath,
25135
25435
  present: true,
25136
- sha256: await sha2564(contractsManifestPath),
25436
+ sha256: await sha2566(contractsManifestPath),
25137
25437
  version: 1,
25138
25438
  ...commands === undefined ? {} : { commands },
25139
25439
  ...routes === undefined ? {} : { routes },
@@ -25156,9 +25456,9 @@ async function assessMigration(options) {
25156
25456
  const diff = diffOpenApiDocuments(await readOpenApiJson(baselinePath), await readOpenApiJson(currentPath));
25157
25457
  openApi = {
25158
25458
  baselinePath,
25159
- baselineSha256: await sha2564(baselinePath),
25459
+ baselineSha256: await sha2566(baselinePath),
25160
25460
  currentPath,
25161
- currentSha256: await sha2564(currentPath),
25461
+ currentSha256: await sha2566(currentPath),
25162
25462
  diff
25163
25463
  };
25164
25464
  if (!diff.ok) {