@aigrc/core 0.1.0 → 0.2.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.js CHANGED
@@ -944,61 +944,165 @@ var init_risk_indicators = __esm({
944
944
  // src/index.ts
945
945
  var index_exports = {};
946
946
  __export(index_exports, {
947
+ AIRBuildConstraintsSchema: () => AIRBuildConstraintsSchema,
948
+ AIRMetadataSchema: () => AIRMetadataSchema,
949
+ AIRModelSchema: () => AIRModelSchema,
950
+ AIRPIIFilterConfigSchema: () => AIRPIIFilterConfigSchema,
951
+ AIRPolicySourceSchema: () => AIRPolicySourceSchema,
952
+ AIRRegionSchema: () => AIRRegionSchema,
953
+ AIRRegistryConstraintsSchema: () => AIRRegistryConstraintsSchema,
954
+ AIRRuntimeConstraintsSchema: () => AIRRuntimeConstraintsSchema,
955
+ AIRSchema: () => AIRSchema,
956
+ AIRToxicityFilterConfigSchema: () => AIRToxicityFilterConfigSchema,
957
+ AIRVendorSchema: () => AIRVendorSchema,
958
+ AigrcConfigSchema: () => AigrcConfigSchema,
959
+ AigrcIntegrationsConfigSchema: () => AigrcIntegrationsConfigSchema,
960
+ AigrcRuntimeConfigSchema: () => AigrcRuntimeConfigSchema,
947
961
  ApprovalSchema: () => ApprovalSchema,
962
+ AssetCardRuntimeSchema: () => AssetCardRuntimeSchema,
948
963
  AssetCardSchema: () => AssetCardSchema,
964
+ CONFIG_ENV_VAR: () => CONFIG_ENV_VAR,
965
+ CONFIG_FILE_NAMES: () => CONFIG_FILE_NAMES,
966
+ CapabilitiesManifestSchema: () => CapabilitiesManifestSchema,
949
967
  ClassificationSchema: () => ClassificationSchema,
950
968
  ConfidenceLevelSchema: () => ConfidenceLevelSchema,
951
969
  ConstraintsSchema: () => ConstraintsSchema,
952
970
  ControlStatusSchema: () => ControlStatusSchema,
953
971
  DetectionStrategySchema: () => DetectionStrategySchema,
954
972
  FrameworkCategorySchema: () => FrameworkCategorySchema,
973
+ GoldenThreadSchema: () => GoldenThreadSchema,
974
+ GovernanceLockBuildConstraintsSchema: () => GovernanceLockBuildConstraintsSchema,
975
+ GovernanceLockConstraintsSchema: () => GovernanceLockConstraintsSchema,
976
+ GovernanceLockPolicySourceSchema: () => GovernanceLockPolicySourceSchema,
977
+ GovernanceLockRegistryConstraintsSchema: () => GovernanceLockRegistryConstraintsSchema,
978
+ GovernanceLockRuntimeConstraintsSchema: () => GovernanceLockRuntimeConstraintsSchema,
979
+ GovernanceLockSchema: () => GovernanceLockSchema,
980
+ GovernanceLockSignatureSchema: () => GovernanceLockSignatureSchema,
955
981
  GovernanceSchema: () => GovernanceSchema,
982
+ GovernanceTokenCapabilityClaimsSchema: () => GovernanceTokenCapabilityClaimsSchema,
983
+ GovernanceTokenControlClaimsSchema: () => GovernanceTokenControlClaimsSchema,
984
+ GovernanceTokenGovernanceClaimsSchema: () => GovernanceTokenGovernanceClaimsSchema,
985
+ GovernanceTokenIdentityClaimsSchema: () => GovernanceTokenIdentityClaimsSchema,
986
+ GovernanceTokenLineageClaimsSchema: () => GovernanceTokenLineageClaimsSchema,
987
+ GovernanceTokenPayloadSchema: () => GovernanceTokenPayloadSchema,
956
988
  IntentSchema: () => IntentSchema,
957
989
  JurisdictionClassificationSchema: () => JurisdictionClassificationSchema,
990
+ KillSwitchCommandSchema: () => KillSwitchCommandSchema,
991
+ KillSwitchCommandTypeSchema: () => KillSwitchCommandTypeSchema,
992
+ LineageSchema: () => LineageSchema,
993
+ MAX_INHERITANCE_DEPTH: () => MAX_INHERITANCE_DEPTH,
958
994
  MODEL_EXTENSIONS: () => MODEL_EXTENSIONS,
995
+ OperatingModeSchema: () => OperatingModeSchema,
959
996
  OwnerSchema: () => OwnerSchema,
997
+ PolicyCapabilitiesSchema: () => PolicyCapabilitiesSchema,
998
+ PolicyFileSchema: () => PolicyFileSchema,
999
+ PolicyResolutionError: () => PolicyResolutionError,
1000
+ PolicyRuleEffectSchema: () => PolicyRuleEffectSchema,
1001
+ PolicyRuleSchema: () => PolicyRuleSchema,
960
1002
  RiskFactorsSchema: () => RiskFactorsSchema,
1003
+ RiskLevelSchema: () => RiskLevelSchema,
1004
+ RuntimeIdentitySchema: () => RuntimeIdentitySchema,
961
1005
  TechnicalSchema: () => TechnicalSchema,
962
1006
  TrustworthinessCharacteristicSchema: () => TrustworthinessCharacteristicSchema,
963
1007
  TrustworthinessSchema: () => TrustworthinessSchema,
964
1008
  addJurisdiction: () => addJurisdiction,
1009
+ addSignature: () => addSignature,
965
1010
  analyzeImports: () => analyzeImports,
966
1011
  applyImplicationChains: () => applyImplicationChains,
967
1012
  classifyRisk: () => classifyRisk,
968
1013
  clearRegistry: () => clearRegistry,
1014
+ compareRiskLevels: () => compareRiskLevels,
1015
+ computeCanonicalString: () => computeCanonicalString,
1016
+ computeGoldenThreadHash: () => computeGoldenThreadHash,
1017
+ computeGoldenThreadHashSync: () => computeGoldenThreadHashSync,
1018
+ computeHash: () => computeHash,
969
1019
  createAssetCard: () => createAssetCard,
1020
+ createDefaultConfig: () => createDefaultConfig,
1021
+ createEmptyAIR: () => createEmptyAIR,
1022
+ createGoldenThread: () => createGoldenThread,
1023
+ createGoldenThreadSync: () => createGoldenThreadSync,
1024
+ createGovernanceLock: () => createGovernanceLock,
970
1025
  createImplication: () => createImplication,
1026
+ createPolicyRepository: () => createPolicyRepository,
1027
+ createPolicySelector: () => createPolicySelector,
1028
+ createSigningPayload: () => createSigningPayload,
971
1029
  detectAnnotations: () => detectAnnotations,
1030
+ discoverAssets: () => discoverAssets,
1031
+ discoverConfig: () => discoverConfig,
1032
+ discoverConfigSync: () => discoverConfigSync,
1033
+ discoverPolicies: () => discoverPolicies,
1034
+ evaluatePolicy: () => evaluatePolicy,
1035
+ extractGoldenThreadComponents: () => extractGoldenThreadComponents,
972
1036
  formatDate: () => formatDate,
973
1037
  generateAssetId: () => generateAssetId,
974
1038
  getAllPatterns: () => getAllPatterns,
1039
+ getCurrentEnvironment: () => getCurrentEnvironment,
1040
+ getDaysUntilExpiration: () => getDaysUntilExpiration,
1041
+ getEnvironmentConfig: () => getEnvironmentConfig,
1042
+ getMaxRiskLevel: () => getMaxRiskLevel,
1043
+ getMinRiskLevel: () => getMinRiskLevel,
975
1044
  getPattern: () => getPattern,
976
1045
  getPatternsByCategory: () => getPatternsByCategory,
977
1046
  getPatternsByLanguage: () => getPatternsByLanguage,
1047
+ getRiskLevelOrdinal: () => getRiskLevelOrdinal,
1048
+ getRiskLevelsAtLeast: () => getRiskLevelsAtLeast,
1049
+ getRiskLevelsAtMost: () => getRiskLevelsAtMost,
978
1050
  inferRiskFactors: () => inferRiskFactors,
979
1051
  initializePatterns: () => initializePatterns,
1052
+ isDomainAllowed: () => isDomainAllowed,
1053
+ isGovernanceLockExpired: () => isGovernanceLockExpired,
1054
+ isModelAllowed: () => isModelAllowed,
1055
+ isModelAllowedByLock: () => isModelAllowedByLock,
980
1056
  isModelFile: () => isModelFile,
1057
+ isRegionAllowed: () => isRegionAllowed,
1058
+ isRegionAllowedByLock: () => isRegionAllowedByLock,
981
1059
  isRegistryInitialized: () => isRegistryInitialized,
1060
+ isRiskLevelAtLeast: () => isRiskLevelAtLeast,
1061
+ isRiskLevelAtMost: () => isRiskLevelAtMost,
1062
+ isToolAllowed: () => isToolAllowed,
1063
+ isValidRiskLevel: () => isValidRiskLevel,
1064
+ isVendorAllowed: () => isVendorAllowed,
1065
+ isVendorAllowedByLock: () => isVendorAllowedByLock,
982
1066
  javascriptPatterns: () => javascriptPatterns,
983
1067
  linkAssetToTicket: () => linkAssetToTicket,
1068
+ loadAsset: () => loadAsset,
984
1069
  loadAssetCard: () => loadAssetCard,
1070
+ loadAssetFromPath: () => loadAssetFromPath,
1071
+ loadPolicy: () => loadPolicy,
1072
+ mapToEuAiActCategory: () => mapToEuAiActCategory,
985
1073
  matchPatterns: () => matchPatterns,
1074
+ mergePolicies: () => mergePolicies,
986
1075
  modelFilePatterns: () => modelFilePatterns,
987
1076
  parseDate: () => parseDate,
1077
+ parseGovernanceLockJSON: () => parseGovernanceLockJSON,
1078
+ parseGovernanceLockYAML: () => parseGovernanceLockYAML,
1079
+ parseRiskLevel: () => parseRiskLevel,
1080
+ parseSignature: () => parseSignature,
988
1081
  pythonPatterns: () => pythonPatterns,
989
1082
  registerPattern: () => registerPattern,
990
1083
  resetPatterns: () => resetPatterns,
1084
+ resolvePolicy: () => resolvePolicy,
991
1085
  riskIndicatorPatterns: () => riskIndicatorPatterns,
992
1086
  saveAssetCard: () => saveAssetCard,
993
1087
  scan: () => scan,
994
1088
  scanFileExtension: () => scanFileExtension,
995
1089
  scanSync: () => scanSync,
1090
+ selectPolicy: () => selectPolicy,
1091
+ serializeGovernanceLockJSON: () => serializeGovernanceLockJSON,
1092
+ serializeGovernanceLockYAML: () => serializeGovernanceLockYAML,
1093
+ signGoldenThread: () => signGoldenThread,
996
1094
  slugify: () => slugify,
997
1095
  suggestAssetCard: () => suggestAssetCard,
998
1096
  updateJurisdictionCompliance: () => updateJurisdictionCompliance,
1097
+ validateAIR: () => validateAIR,
999
1098
  validateAssetCard: () => validateAssetCard,
1000
1099
  validateGoldenThread: () => validateGoldenThread,
1001
- validateRiskFactors: () => validateRiskFactors
1100
+ validateGovernanceLock: () => validateGovernanceLock,
1101
+ validateRiskFactors: () => validateRiskFactors,
1102
+ verifyGoldenThreadHash: () => verifyGoldenThreadHash,
1103
+ verifyGoldenThreadHashSync: () => verifyGoldenThreadHashSync,
1104
+ verifyGoldenThreadSignature: () => verifyGoldenThreadSignature,
1105
+ verifyGoldenThreadSignatureSync: () => verifyGoldenThreadSignatureSync
1002
1106
  });
1003
1107
  module.exports = __toCommonJS(index_exports);
1004
1108
 
@@ -1144,6 +1248,311 @@ var ConstraintsSchema = import_zod.z.object({
1144
1248
  logToolInvocations: import_zod.z.boolean().default(true)
1145
1249
  }).optional()
1146
1250
  });
1251
+ var RiskLevelSchema = import_zod.z.enum(["minimal", "limited", "high", "unacceptable"]);
1252
+ var GoldenThreadSchema = import_zod.z.object({
1253
+ /** Ticket ID from approval system (e.g., "FIN-1234") */
1254
+ ticket_id: import_zod.z.string().min(1),
1255
+ /** Email of approver (e.g., "ciso@corp.com") */
1256
+ approved_by: import_zod.z.string().email(),
1257
+ /** ISO 8601 timestamp of approval (e.g., "2025-01-15T10:30:00Z") */
1258
+ approved_at: import_zod.z.string().datetime(),
1259
+ /** SHA-256 hash of canonical string: sha256:{64 hex chars} */
1260
+ hash: import_zod.z.string().regex(/^sha256:[a-f0-9]{64}$/).optional(),
1261
+ /** Optional cryptographic signature: {ALGORITHM}:{BASE64_SIGNATURE} */
1262
+ signature: import_zod.z.string().regex(/^(RSA-SHA256|ECDSA-P256):[A-Za-z0-9+/=]+$/).optional()
1263
+ });
1264
+ var LineageSchema = import_zod.z.object({
1265
+ /** Parent agent's instance_id, null for root agents */
1266
+ parent_instance_id: import_zod.z.string().uuid().nullable(),
1267
+ /** Depth in spawn tree: 0 for root, 1 for first child, etc. */
1268
+ generation_depth: import_zod.z.number().int().min(0),
1269
+ /** Chain of ancestor instance_ids from root to parent */
1270
+ ancestor_chain: import_zod.z.array(import_zod.z.string().uuid()),
1271
+ /** When this agent was spawned */
1272
+ spawned_at: import_zod.z.string().datetime(),
1273
+ /** Root agent's instance_id for tracing entire tree */
1274
+ root_instance_id: import_zod.z.string().uuid()
1275
+ });
1276
+ var CapabilitiesManifestSchema = import_zod.z.object({
1277
+ /** List of allowed tool/action identifiers (supports wildcards: *, prefix_*) */
1278
+ allowed_tools: import_zod.z.array(import_zod.z.string()).default([]),
1279
+ /** List of explicitly denied tools (takes precedence over allowed) */
1280
+ denied_tools: import_zod.z.array(import_zod.z.string()).default([]),
1281
+ /** Allowed domain patterns (regex) for external resources */
1282
+ allowed_domains: import_zod.z.array(import_zod.z.string()).default([]),
1283
+ /** Denied domain patterns (takes precedence over allowed) */
1284
+ denied_domains: import_zod.z.array(import_zod.z.string()).default([]),
1285
+ /** Maximum cost per session in USD */
1286
+ max_cost_per_session: import_zod.z.number().positive().nullable().optional(),
1287
+ /** Maximum cost per day in USD */
1288
+ max_cost_per_day: import_zod.z.number().positive().nullable().optional(),
1289
+ /** Maximum tokens per single API call */
1290
+ max_tokens_per_call: import_zod.z.number().int().positive().nullable().optional(),
1291
+ /** Whether this agent can spawn child agents */
1292
+ may_spawn_children: import_zod.z.boolean().default(false),
1293
+ /** Maximum depth of child agent spawning (0 = cannot spawn) */
1294
+ max_child_depth: import_zod.z.number().int().min(0).default(0),
1295
+ /** Capability decay mode for children: decay, explicit, inherit */
1296
+ capability_mode: import_zod.z.enum(["decay", "explicit", "inherit"]).default("decay"),
1297
+ /** Custom extension fields */
1298
+ custom: import_zod.z.record(import_zod.z.unknown()).optional()
1299
+ });
1300
+ var OperatingModeSchema = import_zod.z.enum(["NORMAL", "SANDBOX", "RESTRICTED"]);
1301
+ var RuntimeIdentitySchema = import_zod.z.object({
1302
+ /** Unique UUIDv4 for this runtime instance */
1303
+ instance_id: import_zod.z.string().uuid(),
1304
+ /** Asset ID from the Asset Card (e.g., "aigrc-2024-a1b2c3d4") */
1305
+ asset_id: import_zod.z.string().regex(/^aigrc-\d{4}-[a-f0-9]{8}$/),
1306
+ /** Human-readable name from Asset Card */
1307
+ asset_name: import_zod.z.string().min(1).max(100),
1308
+ /** Semantic version from Asset Card */
1309
+ asset_version: import_zod.z.string().regex(/^\d+\.\d+\.\d+/),
1310
+ /** SHA-256 hash of Golden Thread data */
1311
+ golden_thread_hash: import_zod.z.string().regex(/^sha256:[a-f0-9]{64}$/),
1312
+ /** Full Golden Thread authorization data */
1313
+ golden_thread: GoldenThreadSchema,
1314
+ /** Risk level from classification */
1315
+ risk_level: RiskLevelSchema,
1316
+ /** Agent lineage for spawned agents */
1317
+ lineage: LineageSchema,
1318
+ /** Capabilities manifest defining permissions */
1319
+ capabilities_manifest: CapabilitiesManifestSchema,
1320
+ /** When this identity was created */
1321
+ created_at: import_zod.z.string().datetime(),
1322
+ /** Whether Golden Thread hash has been verified */
1323
+ verified: import_zod.z.boolean().default(false),
1324
+ /** Current operating mode */
1325
+ mode: OperatingModeSchema.default("NORMAL")
1326
+ });
1327
+ var KillSwitchCommandTypeSchema = import_zod.z.enum(["TERMINATE", "PAUSE", "RESUME"]);
1328
+ var KillSwitchCommandSchema = import_zod.z.object({
1329
+ /** Unique command ID for idempotency and replay prevention */
1330
+ command_id: import_zod.z.string().uuid(),
1331
+ /** Type of command */
1332
+ type: KillSwitchCommandTypeSchema,
1333
+ /** Target instance_id (optional, for specific instance) */
1334
+ instance_id: import_zod.z.string().uuid().optional(),
1335
+ /** Target asset_id (optional, for all instances of an asset) */
1336
+ asset_id: import_zod.z.string().regex(/^aigrc-\d{4}-[a-f0-9]{8}$/).optional(),
1337
+ /** Target organization (optional, for org-wide kill) */
1338
+ organization: import_zod.z.string().optional(),
1339
+ /** Cryptographic signature for verification */
1340
+ signature: import_zod.z.string(),
1341
+ /** ISO 8601 timestamp for replay prevention */
1342
+ timestamp: import_zod.z.string().datetime(),
1343
+ /** Human-readable reason for audit trail */
1344
+ reason: import_zod.z.string().max(500),
1345
+ /** Issuer of the command (email or system ID) */
1346
+ issued_by: import_zod.z.string()
1347
+ });
1348
+ var GovernanceTokenIdentityClaimsSchema = import_zod.z.object({
1349
+ instance_id: import_zod.z.string().uuid(),
1350
+ asset_id: import_zod.z.string(),
1351
+ asset_name: import_zod.z.string(),
1352
+ asset_version: import_zod.z.string()
1353
+ });
1354
+ var GovernanceTokenGovernanceClaimsSchema = import_zod.z.object({
1355
+ risk_level: RiskLevelSchema,
1356
+ golden_thread: import_zod.z.object({
1357
+ hash: import_zod.z.string().regex(/^sha256:[a-f0-9]{64}$/),
1358
+ verified: import_zod.z.boolean(),
1359
+ ticket_id: import_zod.z.string()
1360
+ }),
1361
+ mode: OperatingModeSchema
1362
+ });
1363
+ var GovernanceTokenControlClaimsSchema = import_zod.z.object({
1364
+ kill_switch: import_zod.z.object({
1365
+ enabled: import_zod.z.boolean(),
1366
+ channel: import_zod.z.enum(["sse", "polling", "file"])
1367
+ }),
1368
+ paused: import_zod.z.boolean(),
1369
+ termination_pending: import_zod.z.boolean()
1370
+ });
1371
+ var GovernanceTokenCapabilityClaimsSchema = import_zod.z.object({
1372
+ hash: import_zod.z.string(),
1373
+ tools: import_zod.z.array(import_zod.z.string()),
1374
+ max_budget_usd: import_zod.z.number().nullable(),
1375
+ can_spawn: import_zod.z.boolean(),
1376
+ max_child_depth: import_zod.z.number().int().min(0)
1377
+ });
1378
+ var GovernanceTokenLineageClaimsSchema = import_zod.z.object({
1379
+ generation_depth: import_zod.z.number().int().min(0),
1380
+ parent_instance_id: import_zod.z.string().uuid().nullable(),
1381
+ root_instance_id: import_zod.z.string().uuid()
1382
+ });
1383
+ var GovernanceTokenPayloadSchema = import_zod.z.object({
1384
+ // Standard JWT claims
1385
+ /** Issuer: "aigos-runtime" */
1386
+ iss: import_zod.z.literal("aigos-runtime"),
1387
+ /** Subject: instance_id of the agent */
1388
+ sub: import_zod.z.string().uuid(),
1389
+ /** Audience: "aigos-agents" or specific agent */
1390
+ aud: import_zod.z.union([import_zod.z.string(), import_zod.z.array(import_zod.z.string())]),
1391
+ /** Expiration timestamp (Unix epoch) */
1392
+ exp: import_zod.z.number().int().positive(),
1393
+ /** Issued at timestamp (Unix epoch) */
1394
+ iat: import_zod.z.number().int().positive(),
1395
+ /** Not before timestamp (Unix epoch) */
1396
+ nbf: import_zod.z.number().int().positive(),
1397
+ /** Unique JWT ID */
1398
+ jti: import_zod.z.string().uuid(),
1399
+ // AIGOS-specific claims
1400
+ aigos: import_zod.z.object({
1401
+ identity: GovernanceTokenIdentityClaimsSchema,
1402
+ governance: GovernanceTokenGovernanceClaimsSchema,
1403
+ control: GovernanceTokenControlClaimsSchema,
1404
+ capabilities: GovernanceTokenCapabilityClaimsSchema,
1405
+ lineage: GovernanceTokenLineageClaimsSchema
1406
+ })
1407
+ });
1408
+ var AssetCardRuntimeSchema = import_zod.z.object({
1409
+ /** Path to policy file for this asset */
1410
+ policy_path: import_zod.z.string().optional(),
1411
+ /** Behavior when Golden Thread verification fails */
1412
+ verification_failure_mode: import_zod.z.enum(["SANDBOX", "FAIL"]).default("SANDBOX"),
1413
+ /** Whether telemetry is enabled for this asset */
1414
+ telemetry_enabled: import_zod.z.boolean().default(true),
1415
+ /** Kill switch configuration */
1416
+ kill_switch: import_zod.z.object({
1417
+ enabled: import_zod.z.boolean().default(true),
1418
+ channel: import_zod.z.enum(["sse", "polling", "file"]).default("sse"),
1419
+ endpoint: import_zod.z.string().url().optional()
1420
+ }).optional()
1421
+ });
1422
+ var PolicyRuleEffectSchema = import_zod.z.enum(["allow", "deny", "audit"]);
1423
+ var PolicyRuleSchema = import_zod.z.object({
1424
+ /** Unique identifier for this rule */
1425
+ id: import_zod.z.string().min(1),
1426
+ /** Human-readable description */
1427
+ description: import_zod.z.string().optional(),
1428
+ /** Effect when rule matches: allow, deny, or audit */
1429
+ effect: PolicyRuleEffectSchema,
1430
+ /** Actions/tools this rule applies to (supports wildcards) */
1431
+ actions: import_zod.z.array(import_zod.z.string()).default(["*"]),
1432
+ /** Resources/domains this rule applies to (supports patterns) */
1433
+ resources: import_zod.z.array(import_zod.z.string()).default(["*"]),
1434
+ /** Conditions that must be true for rule to apply */
1435
+ conditions: import_zod.z.object({
1436
+ /** Required risk levels for this rule to apply */
1437
+ risk_levels: import_zod.z.array(RiskLevelSchema).optional(),
1438
+ /** Required operating modes */
1439
+ modes: import_zod.z.array(OperatingModeSchema).optional(),
1440
+ /** Time-based conditions (ISO 8601 time ranges) */
1441
+ time_ranges: import_zod.z.array(import_zod.z.object({
1442
+ start: import_zod.z.string(),
1443
+ end: import_zod.z.string()
1444
+ })).optional(),
1445
+ /** Custom condition expressions */
1446
+ custom: import_zod.z.record(import_zod.z.unknown()).optional()
1447
+ }).optional(),
1448
+ /** Priority for rule ordering (higher = evaluated first) */
1449
+ priority: import_zod.z.number().int().default(0)
1450
+ });
1451
+ var PolicyCapabilitiesSchema = import_zod.z.object({
1452
+ /** Default effect when no rule matches */
1453
+ default_effect: PolicyRuleEffectSchema.default("deny"),
1454
+ /** Allowed tools (supports wildcards: *, prefix_*) */
1455
+ allowed_tools: import_zod.z.array(import_zod.z.string()).default([]),
1456
+ /** Denied tools (takes precedence) */
1457
+ denied_tools: import_zod.z.array(import_zod.z.string()).default([]),
1458
+ /** Allowed domain patterns */
1459
+ allowed_domains: import_zod.z.array(import_zod.z.string()).default([]),
1460
+ /** Denied domain patterns */
1461
+ denied_domains: import_zod.z.array(import_zod.z.string()).default([]),
1462
+ /** Maximum budget per session in USD */
1463
+ max_budget_per_session: import_zod.z.number().positive().nullable().optional(),
1464
+ /** Maximum budget per day in USD */
1465
+ max_budget_per_day: import_zod.z.number().positive().nullable().optional(),
1466
+ /** Whether agent can spawn children */
1467
+ may_spawn: import_zod.z.boolean().default(false),
1468
+ /** Maximum spawn depth */
1469
+ max_spawn_depth: import_zod.z.number().int().min(0).default(0)
1470
+ });
1471
+ var PolicyFileSchema = import_zod.z.object({
1472
+ /** Schema version for forward compatibility */
1473
+ version: import_zod.z.literal("1.0"),
1474
+ /** Unique policy identifier */
1475
+ id: import_zod.z.string().min(1),
1476
+ /** Human-readable name */
1477
+ name: import_zod.z.string().min(1).max(100),
1478
+ /** Description of this policy */
1479
+ description: import_zod.z.string().max(500).optional(),
1480
+ /** Parent policy to inherit from */
1481
+ extends: import_zod.z.string().optional(),
1482
+ /** Target asset IDs or patterns this policy applies to */
1483
+ applies_to: import_zod.z.array(import_zod.z.string()).default(["*"]),
1484
+ /** Default capabilities when no rules match */
1485
+ capabilities: PolicyCapabilitiesSchema.optional(),
1486
+ /** Ordered list of policy rules */
1487
+ rules: import_zod.z.array(PolicyRuleSchema).default([]),
1488
+ /** Metadata */
1489
+ metadata: import_zod.z.object({
1490
+ created_at: import_zod.z.string().datetime().optional(),
1491
+ updated_at: import_zod.z.string().datetime().optional(),
1492
+ created_by: import_zod.z.string().optional(),
1493
+ tags: import_zod.z.array(import_zod.z.string()).optional()
1494
+ }).optional()
1495
+ });
1496
+ var AigrcRuntimeConfigSchema = import_zod.z.object({
1497
+ /** Default policy file path */
1498
+ default_policy: import_zod.z.string().optional(),
1499
+ /** Policy search paths */
1500
+ policy_paths: import_zod.z.array(import_zod.z.string()).default([".aigrc/policies"]),
1501
+ /** Asset card search paths */
1502
+ asset_paths: import_zod.z.array(import_zod.z.string()).default([".aigrc/assets"]),
1503
+ /** Default verification failure mode */
1504
+ verification_failure_mode: import_zod.z.enum(["SANDBOX", "FAIL"]).default("SANDBOX"),
1505
+ /** Telemetry configuration */
1506
+ telemetry: import_zod.z.object({
1507
+ enabled: import_zod.z.boolean().default(true),
1508
+ endpoint: import_zod.z.string().url().optional(),
1509
+ sample_rate: import_zod.z.number().min(0).max(1).default(1)
1510
+ }).optional(),
1511
+ /** Kill switch configuration */
1512
+ kill_switch: import_zod.z.object({
1513
+ enabled: import_zod.z.boolean().default(true),
1514
+ channel: import_zod.z.enum(["sse", "polling", "file"]).default("sse"),
1515
+ endpoint: import_zod.z.string().url().optional(),
1516
+ poll_interval_ms: import_zod.z.number().int().positive().default(5e3)
1517
+ }).optional()
1518
+ });
1519
+ var AigrcIntegrationsConfigSchema = import_zod.z.object({
1520
+ /** JIRA integration */
1521
+ jira: import_zod.z.object({
1522
+ enabled: import_zod.z.boolean().default(false),
1523
+ url: import_zod.z.string().url().optional(),
1524
+ project_key: import_zod.z.string().optional()
1525
+ }).optional(),
1526
+ /** Azure DevOps integration */
1527
+ azure_devops: import_zod.z.object({
1528
+ enabled: import_zod.z.boolean().default(false),
1529
+ organization: import_zod.z.string().optional(),
1530
+ project: import_zod.z.string().optional()
1531
+ }).optional(),
1532
+ /** GitHub integration */
1533
+ github: import_zod.z.object({
1534
+ enabled: import_zod.z.boolean().default(false),
1535
+ owner: import_zod.z.string().optional(),
1536
+ repo: import_zod.z.string().optional()
1537
+ }).optional()
1538
+ });
1539
+ var AigrcConfigSchema = import_zod.z.object({
1540
+ /** Schema version */
1541
+ version: import_zod.z.literal("1.0"),
1542
+ /** Project name */
1543
+ name: import_zod.z.string().min(1).max(100).optional(),
1544
+ /** Project description */
1545
+ description: import_zod.z.string().max(500).optional(),
1546
+ /** Runtime governance configuration */
1547
+ runtime: AigrcRuntimeConfigSchema.optional(),
1548
+ /** External integrations */
1549
+ integrations: AigrcIntegrationsConfigSchema.optional(),
1550
+ /** Environment-specific overrides */
1551
+ environments: import_zod.z.record(import_zod.z.object({
1552
+ runtime: AigrcRuntimeConfigSchema.partial().optional(),
1553
+ integrations: AigrcIntegrationsConfigSchema.partial().optional()
1554
+ })).optional()
1555
+ });
1147
1556
  var AssetCardSchema = import_zod.z.object({
1148
1557
  $schema: import_zod.z.string().optional(),
1149
1558
  id: import_zod.z.string().regex(/^aigrc-\d{4}-[a-f0-9]{8}$/),
@@ -1160,7 +1569,11 @@ var AssetCardSchema = import_zod.z.object({
1160
1569
  classification: ClassificationSchema,
1161
1570
  intent: IntentSchema,
1162
1571
  governance: GovernanceSchema,
1163
- constraints: ConstraintsSchema.optional()
1572
+ constraints: ConstraintsSchema.optional(),
1573
+ /** Golden Thread authorization data (SPEC-PRT-001) */
1574
+ golden_thread: GoldenThreadSchema.optional(),
1575
+ /** Runtime governance configuration (SPEC-RT) */
1576
+ runtime: AssetCardRuntimeSchema.optional()
1164
1577
  });
1165
1578
 
1166
1579
  // src/classification.ts
@@ -1231,6 +1644,73 @@ function validateRiskFactors(factors) {
1231
1644
  return true;
1232
1645
  }
1233
1646
 
1647
+ // src/risk-utils.ts
1648
+ var RISK_ORDINALS = {
1649
+ minimal: 0,
1650
+ limited: 1,
1651
+ high: 2,
1652
+ unacceptable: 3
1653
+ };
1654
+ var EU_AI_ACT_MAP = {
1655
+ minimal: "minimal_risk",
1656
+ limited: "limited_risk",
1657
+ high: "high_risk",
1658
+ unacceptable: "prohibited"
1659
+ };
1660
+ function compareRiskLevels(a, b) {
1661
+ const ordA = RISK_ORDINALS[a];
1662
+ const ordB = RISK_ORDINALS[b];
1663
+ if (ordA < ordB) return -1;
1664
+ if (ordA > ordB) return 1;
1665
+ return 0;
1666
+ }
1667
+ function isRiskLevelAtLeast(level, threshold) {
1668
+ return RISK_ORDINALS[level] >= RISK_ORDINALS[threshold];
1669
+ }
1670
+ function isRiskLevelAtMost(level, threshold) {
1671
+ return RISK_ORDINALS[level] <= RISK_ORDINALS[threshold];
1672
+ }
1673
+ function getRiskLevelOrdinal(level) {
1674
+ return RISK_ORDINALS[level];
1675
+ }
1676
+ function getMaxRiskLevel(levels) {
1677
+ if (levels.length === 0) {
1678
+ return "minimal";
1679
+ }
1680
+ return levels.reduce(
1681
+ (max, current) => RISK_ORDINALS[current] > RISK_ORDINALS[max] ? current : max
1682
+ );
1683
+ }
1684
+ function getMinRiskLevel(levels) {
1685
+ if (levels.length === 0) {
1686
+ return "minimal";
1687
+ }
1688
+ return levels.reduce(
1689
+ (min, current) => RISK_ORDINALS[current] < RISK_ORDINALS[min] ? current : min
1690
+ );
1691
+ }
1692
+ function mapToEuAiActCategory(level) {
1693
+ return EU_AI_ACT_MAP[level];
1694
+ }
1695
+ function getRiskLevelsAtLeast(threshold) {
1696
+ const thresholdOrd = RISK_ORDINALS[threshold];
1697
+ return Object.entries(RISK_ORDINALS).filter(([, ord]) => ord >= thresholdOrd).map(([level]) => level);
1698
+ }
1699
+ function getRiskLevelsAtMost(threshold) {
1700
+ const thresholdOrd = RISK_ORDINALS[threshold];
1701
+ return Object.entries(RISK_ORDINALS).filter(([, ord]) => ord <= thresholdOrd).map(([level]) => level);
1702
+ }
1703
+ function parseRiskLevel(value) {
1704
+ const normalized = value.toLowerCase();
1705
+ if (normalized in RISK_ORDINALS) {
1706
+ return normalized;
1707
+ }
1708
+ return void 0;
1709
+ }
1710
+ function isValidRiskLevel(value) {
1711
+ return typeof value === "string" && value in RISK_ORDINALS;
1712
+ }
1713
+
1234
1714
  // src/asset-card.ts
1235
1715
  var import_fs = require("fs");
1236
1716
  var import_path = require("path");
@@ -1380,6 +1860,115 @@ function validateAssetCard(card) {
1380
1860
  }
1381
1861
 
1382
1862
  // src/golden-thread.ts
1863
+ function computeCanonicalString(components) {
1864
+ const normalizedTimestamp = normalizeTimestamp(components.approved_at);
1865
+ const pairs = [
1866
+ `approved_at=${normalizedTimestamp}`,
1867
+ `approved_by=${components.approved_by}`,
1868
+ `ticket_id=${components.ticket_id}`
1869
+ ];
1870
+ return pairs.join("|");
1871
+ }
1872
+ function normalizeTimestamp(timestamp) {
1873
+ const date = new Date(timestamp);
1874
+ if (isNaN(date.getTime())) {
1875
+ throw new Error(`Invalid timestamp: ${timestamp}`);
1876
+ }
1877
+ return date.toISOString().replace(/\.\d{3}Z$/, "Z");
1878
+ }
1879
+ async function computeGoldenThreadHash(components) {
1880
+ const canonicalString = computeCanonicalString(components);
1881
+ const encoder = new TextEncoder();
1882
+ const data = encoder.encode(canonicalString);
1883
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
1884
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
1885
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
1886
+ return {
1887
+ canonical_string: canonicalString,
1888
+ hash: `sha256:${hashHex}`
1889
+ };
1890
+ }
1891
+ function computeGoldenThreadHashSync(components) {
1892
+ const canonicalString = computeCanonicalString(components);
1893
+ const crypto2 = require("crypto");
1894
+ const hash = crypto2.createHash("sha256").update(canonicalString).digest("hex");
1895
+ return {
1896
+ canonical_string: canonicalString,
1897
+ hash: `sha256:${hash}`
1898
+ };
1899
+ }
1900
+ async function verifyGoldenThreadHash(components, expectedHash) {
1901
+ const { hash: computedHash } = await computeGoldenThreadHash(components);
1902
+ const verified = constantTimeEqual(computedHash, expectedHash);
1903
+ return {
1904
+ verified,
1905
+ computed: computedHash,
1906
+ expected: expectedHash,
1907
+ mismatch_reason: verified ? void 0 : "Hash mismatch"
1908
+ };
1909
+ }
1910
+ function verifyGoldenThreadHashSync(components, expectedHash) {
1911
+ const { hash: computedHash } = computeGoldenThreadHashSync(components);
1912
+ const verified = constantTimeEqual(computedHash, expectedHash);
1913
+ return {
1914
+ verified,
1915
+ computed: computedHash,
1916
+ expected: expectedHash,
1917
+ mismatch_reason: verified ? void 0 : "Hash mismatch"
1918
+ };
1919
+ }
1920
+ function constantTimeEqual(a, b) {
1921
+ if (a.length !== b.length) {
1922
+ return false;
1923
+ }
1924
+ let result = 0;
1925
+ for (let i = 0; i < a.length; i++) {
1926
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
1927
+ }
1928
+ return result === 0;
1929
+ }
1930
+ function extractGoldenThreadComponents(asset) {
1931
+ if (asset.golden_thread) {
1932
+ return {
1933
+ ticket_id: asset.golden_thread.ticket_id,
1934
+ approved_by: asset.golden_thread.approved_by,
1935
+ approved_at: asset.golden_thread.approved_at
1936
+ };
1937
+ }
1938
+ if (!asset.intent.ticketId) {
1939
+ return null;
1940
+ }
1941
+ const approvals = asset.governance.approvals;
1942
+ if (approvals.length === 0) {
1943
+ return null;
1944
+ }
1945
+ const latestApproval = approvals.reduce(
1946
+ (latest, current) => new Date(current.date) > new Date(latest.date) ? current : latest
1947
+ );
1948
+ return {
1949
+ ticket_id: asset.intent.ticketId,
1950
+ approved_by: latestApproval.email || latestApproval.name,
1951
+ approved_at: latestApproval.date
1952
+ };
1953
+ }
1954
+ async function createGoldenThread(components) {
1955
+ const { hash } = await computeGoldenThreadHash(components);
1956
+ return {
1957
+ ticket_id: components.ticket_id,
1958
+ approved_by: components.approved_by,
1959
+ approved_at: components.approved_at,
1960
+ hash
1961
+ };
1962
+ }
1963
+ function createGoldenThreadSync(components) {
1964
+ const { hash } = computeGoldenThreadHashSync(components);
1965
+ return {
1966
+ ticket_id: components.ticket_id,
1967
+ approved_by: components.approved_by,
1968
+ approved_at: components.approved_at,
1969
+ hash
1970
+ };
1971
+ }
1383
1972
  function linkAssetToTicket(asset, ticket) {
1384
1973
  const warnings = [];
1385
1974
  const intent = {
@@ -1428,6 +2017,144 @@ function validateGoldenThread(asset) {
1428
2017
  issues
1429
2018
  };
1430
2019
  }
2020
+ function parseSignature(signature) {
2021
+ const match = signature.match(/^(RSA-SHA256|ECDSA-P256):([A-Za-z0-9+/=]+)$/);
2022
+ if (!match) {
2023
+ return null;
2024
+ }
2025
+ const algorithm = match[1];
2026
+ const base64Data = match[2];
2027
+ try {
2028
+ const binaryString = atob(base64Data);
2029
+ const bytes = new Uint8Array(binaryString.length);
2030
+ for (let i = 0; i < binaryString.length; i++) {
2031
+ bytes[i] = binaryString.charCodeAt(i);
2032
+ }
2033
+ return { algorithm, data: bytes };
2034
+ } catch {
2035
+ return null;
2036
+ }
2037
+ }
2038
+ async function verifyGoldenThreadSignature(components, signature, publicKey) {
2039
+ const parsed = parseSignature(signature);
2040
+ if (!parsed) {
2041
+ return {
2042
+ verified: false,
2043
+ algorithm: null,
2044
+ error: "Invalid signature format. Expected {ALGORITHM}:{BASE64_SIGNATURE}"
2045
+ };
2046
+ }
2047
+ if (parsed.algorithm !== publicKey.algorithm) {
2048
+ return {
2049
+ verified: false,
2050
+ algorithm: parsed.algorithm,
2051
+ error: `Algorithm mismatch: signature uses ${parsed.algorithm}, key is ${publicKey.algorithm}`
2052
+ };
2053
+ }
2054
+ const canonicalString = computeCanonicalString(components);
2055
+ const encoder = new TextEncoder();
2056
+ const data = encoder.encode(canonicalString);
2057
+ try {
2058
+ const cryptoKey = await importPublicKey(publicKey);
2059
+ const algorithmParams = getVerifyAlgorithm(parsed.algorithm);
2060
+ const verified = await crypto.subtle.verify(
2061
+ algorithmParams,
2062
+ cryptoKey,
2063
+ parsed.data,
2064
+ data
2065
+ );
2066
+ return {
2067
+ verified,
2068
+ algorithm: parsed.algorithm,
2069
+ signedData: canonicalString,
2070
+ error: verified ? void 0 : "Signature verification failed"
2071
+ };
2072
+ } catch (error) {
2073
+ return {
2074
+ verified: false,
2075
+ algorithm: parsed.algorithm,
2076
+ error: `Verification error: ${error instanceof Error ? error.message : String(error)}`
2077
+ };
2078
+ }
2079
+ }
2080
+ function verifyGoldenThreadSignatureSync(components, signature, publicKeyPem) {
2081
+ const parsed = parseSignature(signature);
2082
+ if (!parsed) {
2083
+ return {
2084
+ verified: false,
2085
+ algorithm: null,
2086
+ error: "Invalid signature format"
2087
+ };
2088
+ }
2089
+ const canonicalString = computeCanonicalString(components);
2090
+ try {
2091
+ const crypto2 = require("crypto");
2092
+ const verifier = crypto2.createVerify(
2093
+ parsed.algorithm === "RSA-SHA256" ? "RSA-SHA256" : "SHA256"
2094
+ );
2095
+ verifier.update(canonicalString);
2096
+ verifier.end();
2097
+ const verified = verifier.verify(publicKeyPem, Buffer.from(parsed.data));
2098
+ return {
2099
+ verified,
2100
+ algorithm: parsed.algorithm,
2101
+ signedData: canonicalString,
2102
+ error: verified ? void 0 : "Signature verification failed"
2103
+ };
2104
+ } catch (error) {
2105
+ return {
2106
+ verified: false,
2107
+ algorithm: parsed.algorithm,
2108
+ error: `Verification error: ${error instanceof Error ? error.message : String(error)}`
2109
+ };
2110
+ }
2111
+ }
2112
+ async function signGoldenThread(components, privateKey, algorithm) {
2113
+ const canonicalString = computeCanonicalString(components);
2114
+ const encoder = new TextEncoder();
2115
+ const data = encoder.encode(canonicalString);
2116
+ const signatureBuffer = await crypto.subtle.sign(
2117
+ getSignAlgorithm(algorithm),
2118
+ privateKey,
2119
+ data
2120
+ );
2121
+ const signatureArray = new Uint8Array(signatureBuffer);
2122
+ const base64 = btoa(String.fromCharCode(...signatureArray));
2123
+ return `${algorithm}:${base64}`;
2124
+ }
2125
+ async function importPublicKey(publicKey) {
2126
+ const pemHeader = "-----BEGIN PUBLIC KEY-----";
2127
+ const pemFooter = "-----END PUBLIC KEY-----";
2128
+ let keyData;
2129
+ if (publicKey.key.includes(pemHeader)) {
2130
+ const pemContents = publicKey.key.replace(pemHeader, "").replace(pemFooter, "").replace(/\s/g, "");
2131
+ const binaryString = atob(pemContents);
2132
+ const bytes = new Uint8Array(binaryString.length);
2133
+ for (let i = 0; i < binaryString.length; i++) {
2134
+ bytes[i] = binaryString.charCodeAt(i);
2135
+ }
2136
+ keyData = bytes.buffer;
2137
+ } else {
2138
+ const binaryString = atob(publicKey.key);
2139
+ const bytes = new Uint8Array(binaryString.length);
2140
+ for (let i = 0; i < binaryString.length; i++) {
2141
+ bytes[i] = binaryString.charCodeAt(i);
2142
+ }
2143
+ keyData = bytes.buffer;
2144
+ }
2145
+ const algorithm = publicKey.algorithm === "RSA-SHA256" ? { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" } : { name: "ECDSA", namedCurve: "P-256" };
2146
+ return crypto.subtle.importKey("spki", keyData, algorithm, true, ["verify"]);
2147
+ }
2148
+ function getVerifyAlgorithm(algorithm) {
2149
+ if (algorithm === "RSA-SHA256") {
2150
+ return { name: "RSASSA-PKCS1-v1_5" };
2151
+ } else {
2152
+ return { name: "ECDSA", hash: "SHA-256" };
2153
+ }
2154
+ }
2155
+ function getSignAlgorithm(algorithm) {
2156
+ return getVerifyAlgorithm(algorithm);
2157
+ }
1431
2158
 
1432
2159
  // src/detection/types.ts
1433
2160
  var import_zod2 = require("zod");
@@ -2266,6 +2993,1385 @@ init_javascript();
2266
2993
  init_model_files();
2267
2994
  init_risk_indicators();
2268
2995
 
2996
+ // src/config.ts
2997
+ var fs = __toESM(require("fs"));
2998
+ var path = __toESM(require("path"));
2999
+ var yaml = __toESM(require("yaml"));
3000
+ var CONFIG_FILE_NAMES = [
3001
+ ".aigrc.yaml",
3002
+ ".aigrc.yml",
3003
+ "aigrc.yaml",
3004
+ "aigrc.yml"
3005
+ ];
3006
+ var CONFIG_ENV_VAR = "AIGRC_CONFIG_PATH";
3007
+ function discoverConfig(options = {}) {
3008
+ const { startDir = process.cwd(), maxDepth = 10 } = options;
3009
+ if (options.configPath) {
3010
+ const result = loadConfigFromPath(options.configPath);
3011
+ if (result) {
3012
+ return { ...result, fromEnv: false };
3013
+ }
3014
+ }
3015
+ const envPath = process.env[CONFIG_ENV_VAR];
3016
+ if (envPath) {
3017
+ const result = loadConfigFromPath(envPath);
3018
+ if (result) {
3019
+ return { ...result, fromEnv: true };
3020
+ }
3021
+ }
3022
+ let currentDir = path.resolve(startDir);
3023
+ let depth = 0;
3024
+ while (depth < maxDepth) {
3025
+ for (const fileName of CONFIG_FILE_NAMES) {
3026
+ const filePath = path.join(currentDir, fileName);
3027
+ if (fs.existsSync(filePath)) {
3028
+ const config = loadConfigFile(filePath);
3029
+ if (config) {
3030
+ return {
3031
+ config,
3032
+ configPath: filePath,
3033
+ configDir: currentDir,
3034
+ fromEnv: false
3035
+ };
3036
+ }
3037
+ }
3038
+ }
3039
+ const parentDir = path.dirname(currentDir);
3040
+ if (parentDir === currentDir) {
3041
+ break;
3042
+ }
3043
+ currentDir = parentDir;
3044
+ depth++;
3045
+ }
3046
+ return null;
3047
+ }
3048
+ function loadConfigFromPath(configPath) {
3049
+ const resolvedPath = path.resolve(configPath);
3050
+ if (!fs.existsSync(resolvedPath)) {
3051
+ return null;
3052
+ }
3053
+ const config = loadConfigFile(resolvedPath);
3054
+ if (!config) {
3055
+ return null;
3056
+ }
3057
+ return {
3058
+ config,
3059
+ configPath: resolvedPath,
3060
+ configDir: path.dirname(resolvedPath)
3061
+ };
3062
+ }
3063
+ function loadConfigFile(filePath) {
3064
+ try {
3065
+ const content = fs.readFileSync(filePath, "utf-8");
3066
+ const parsed = yaml.parse(content);
3067
+ return AigrcConfigSchema.parse(parsed);
3068
+ } catch {
3069
+ return null;
3070
+ }
3071
+ }
3072
+ function discoverConfigSync(options = {}) {
3073
+ return discoverConfig(options);
3074
+ }
3075
+ function discoverPolicies(options = {}) {
3076
+ const {
3077
+ config,
3078
+ baseDir = process.cwd(),
3079
+ additionalPaths = []
3080
+ } = options;
3081
+ const policies = /* @__PURE__ */ new Map();
3082
+ const loadedPaths = [];
3083
+ const errors = [];
3084
+ const searchPaths = [
3085
+ ...config?.runtime?.policy_paths ?? [".aigrc/policies"],
3086
+ ...additionalPaths
3087
+ ];
3088
+ for (const searchPath of searchPaths) {
3089
+ const absolutePath = path.isAbsolute(searchPath) ? searchPath : path.join(baseDir, searchPath);
3090
+ if (!fs.existsSync(absolutePath)) {
3091
+ continue;
3092
+ }
3093
+ const stat = fs.statSync(absolutePath);
3094
+ if (stat.isDirectory()) {
3095
+ const files = fs.readdirSync(absolutePath);
3096
+ for (const file of files) {
3097
+ if (file.endsWith(".yaml") || file.endsWith(".yml")) {
3098
+ const filePath = path.join(absolutePath, file);
3099
+ const result = loadPolicyFile(filePath);
3100
+ if (result.policy) {
3101
+ policies.set(result.policy.id, result.policy);
3102
+ loadedPaths.push(filePath);
3103
+ } else if (result.error) {
3104
+ errors.push({ path: filePath, error: result.error });
3105
+ }
3106
+ }
3107
+ }
3108
+ } else if (stat.isFile()) {
3109
+ const result = loadPolicyFile(absolutePath);
3110
+ if (result.policy) {
3111
+ policies.set(result.policy.id, result.policy);
3112
+ loadedPaths.push(absolutePath);
3113
+ } else if (result.error) {
3114
+ errors.push({ path: absolutePath, error: result.error });
3115
+ }
3116
+ }
3117
+ }
3118
+ return { policies, loadedPaths, errors };
3119
+ }
3120
+ function loadPolicyFile(filePath) {
3121
+ try {
3122
+ const content = fs.readFileSync(filePath, "utf-8");
3123
+ const parsed = yaml.parse(content);
3124
+ const policy = PolicyFileSchema.parse(parsed);
3125
+ return { policy, error: null };
3126
+ } catch (err) {
3127
+ const message = err instanceof Error ? err.message : String(err);
3128
+ return { policy: null, error: message };
3129
+ }
3130
+ }
3131
+ function loadPolicy(policyId, options = {}) {
3132
+ const { policies } = discoverPolicies(options);
3133
+ return policies.get(policyId) ?? null;
3134
+ }
3135
+ function discoverAssets(options = {}) {
3136
+ const {
3137
+ config,
3138
+ baseDir = process.cwd(),
3139
+ additionalPaths = []
3140
+ } = options;
3141
+ const assets = /* @__PURE__ */ new Map();
3142
+ const loadedPaths = [];
3143
+ const errors = [];
3144
+ const searchPaths = [
3145
+ ...config?.runtime?.asset_paths ?? [".aigrc/assets"],
3146
+ ...additionalPaths
3147
+ ];
3148
+ for (const searchPath of searchPaths) {
3149
+ const absolutePath = path.isAbsolute(searchPath) ? searchPath : path.join(baseDir, searchPath);
3150
+ if (!fs.existsSync(absolutePath)) {
3151
+ continue;
3152
+ }
3153
+ const stat = fs.statSync(absolutePath);
3154
+ if (stat.isDirectory()) {
3155
+ const files = fs.readdirSync(absolutePath);
3156
+ for (const file of files) {
3157
+ if (file.endsWith(".yaml") || file.endsWith(".yml")) {
3158
+ const filePath = path.join(absolutePath, file);
3159
+ const result = loadAssetFile(filePath);
3160
+ if (result.asset) {
3161
+ assets.set(result.asset.id, result.asset);
3162
+ loadedPaths.push(filePath);
3163
+ } else if (result.error) {
3164
+ errors.push({ path: filePath, error: result.error });
3165
+ }
3166
+ }
3167
+ }
3168
+ } else if (stat.isFile()) {
3169
+ const result = loadAssetFile(absolutePath);
3170
+ if (result.asset) {
3171
+ assets.set(result.asset.id, result.asset);
3172
+ loadedPaths.push(absolutePath);
3173
+ } else if (result.error) {
3174
+ errors.push({ path: absolutePath, error: result.error });
3175
+ }
3176
+ }
3177
+ }
3178
+ return { assets, loadedPaths, errors };
3179
+ }
3180
+ function loadAssetFile(filePath) {
3181
+ try {
3182
+ const content = fs.readFileSync(filePath, "utf-8");
3183
+ const parsed = yaml.parse(content);
3184
+ const asset = AssetCardSchema.parse(parsed);
3185
+ return { asset, error: null };
3186
+ } catch (err) {
3187
+ const message = err instanceof Error ? err.message : String(err);
3188
+ return { asset: null, error: message };
3189
+ }
3190
+ }
3191
+ function loadAsset(assetId, options = {}) {
3192
+ const { assets } = discoverAssets(options);
3193
+ return assets.get(assetId) ?? null;
3194
+ }
3195
+ function loadAssetFromPath(filePath) {
3196
+ const result = loadAssetFile(filePath);
3197
+ return result.asset;
3198
+ }
3199
+ function getEnvironmentConfig(config, environment) {
3200
+ const envOverrides = config.environments?.[environment];
3201
+ if (!envOverrides) {
3202
+ return config;
3203
+ }
3204
+ const result = { ...config };
3205
+ if (config.runtime || envOverrides.runtime) {
3206
+ result.runtime = {
3207
+ ...config.runtime,
3208
+ ...filterUndefined(envOverrides.runtime ?? {})
3209
+ };
3210
+ }
3211
+ if (config.integrations || envOverrides.integrations) {
3212
+ result.integrations = {
3213
+ ...config.integrations,
3214
+ ...filterUndefined(envOverrides.integrations ?? {})
3215
+ };
3216
+ }
3217
+ return result;
3218
+ }
3219
+ function filterUndefined(obj) {
3220
+ const result = {};
3221
+ for (const key of Object.keys(obj)) {
3222
+ if (obj[key] !== void 0) {
3223
+ result[key] = obj[key];
3224
+ }
3225
+ }
3226
+ return result;
3227
+ }
3228
+ function getCurrentEnvironment() {
3229
+ return process.env.AIGRC_ENV ?? process.env.NODE_ENV ?? "development";
3230
+ }
3231
+ function createDefaultConfig() {
3232
+ return AigrcConfigSchema.parse({
3233
+ version: "1.0",
3234
+ runtime: {},
3235
+ integrations: {}
3236
+ });
3237
+ }
3238
+
3239
+ // src/policy.ts
3240
+ var MAX_INHERITANCE_DEPTH = 10;
3241
+ var PolicyResolutionError = class extends Error {
3242
+ constructor(message, policyId, cause) {
3243
+ super(message);
3244
+ this.policyId = policyId;
3245
+ this.cause = cause;
3246
+ this.name = "PolicyResolutionError";
3247
+ }
3248
+ };
3249
+ function createPolicyRepository(policies) {
3250
+ return {
3251
+ get: (id) => policies.get(id),
3252
+ has: (id) => policies.has(id)
3253
+ };
3254
+ }
3255
+ function resolvePolicy(policyId, repository) {
3256
+ const chain = [];
3257
+ const seenIds = /* @__PURE__ */ new Set();
3258
+ let currentId = policyId;
3259
+ while (currentId) {
3260
+ if (seenIds.has(currentId)) {
3261
+ throw new PolicyResolutionError(
3262
+ `Circular inheritance detected: ${currentId}`,
3263
+ policyId
3264
+ );
3265
+ }
3266
+ if (chain.length >= MAX_INHERITANCE_DEPTH) {
3267
+ throw new PolicyResolutionError(
3268
+ `Maximum inheritance depth (${MAX_INHERITANCE_DEPTH}) exceeded`,
3269
+ policyId
3270
+ );
3271
+ }
3272
+ const policy = repository.get(currentId);
3273
+ if (!policy) {
3274
+ throw new PolicyResolutionError(
3275
+ `Policy not found: ${currentId}`,
3276
+ policyId
3277
+ );
3278
+ }
3279
+ seenIds.add(currentId);
3280
+ chain.push(policy);
3281
+ currentId = policy.extends;
3282
+ }
3283
+ chain.reverse();
3284
+ const mergedPolicy = chain.reduce(
3285
+ (accumulated, current) => mergePolicies(accumulated, current),
3286
+ createEmptyPolicy(chain[0]?.id ?? policyId)
3287
+ );
3288
+ mergedPolicy.id = policyId;
3289
+ return {
3290
+ policy: mergedPolicy,
3291
+ inheritanceChain: chain.map((p) => p.id),
3292
+ depth: chain.length
3293
+ };
3294
+ }
3295
+ function createEmptyPolicy(id) {
3296
+ return {
3297
+ version: "1.0",
3298
+ id,
3299
+ name: "",
3300
+ applies_to: [],
3301
+ rules: []
3302
+ };
3303
+ }
3304
+ function mergePolicies(parent, child) {
3305
+ return {
3306
+ version: child.version,
3307
+ id: child.id,
3308
+ name: child.name || parent.name,
3309
+ description: child.description ?? parent.description,
3310
+ extends: child.extends,
3311
+ // Keep child's extends for reference
3312
+ applies_to: child.applies_to.length > 0 && child.applies_to[0] !== "*" ? child.applies_to : parent.applies_to,
3313
+ capabilities: mergeCapabilities(parent.capabilities, child.capabilities),
3314
+ rules: mergeRules(parent.rules, child.rules),
3315
+ metadata: {
3316
+ ...parent.metadata,
3317
+ ...child.metadata,
3318
+ // Merge tags
3319
+ tags: mergeArrays(parent.metadata?.tags, child.metadata?.tags)
3320
+ }
3321
+ };
3322
+ }
3323
+ function mergeCapabilities(parent, child) {
3324
+ if (!parent && !child) {
3325
+ return void 0;
3326
+ }
3327
+ if (!parent) {
3328
+ return child;
3329
+ }
3330
+ if (!child) {
3331
+ return parent;
3332
+ }
3333
+ return {
3334
+ default_effect: child.default_effect ?? parent.default_effect,
3335
+ allowed_tools: mergeArrays(parent.allowed_tools, child.allowed_tools),
3336
+ denied_tools: mergeArrays(parent.denied_tools, child.denied_tools),
3337
+ allowed_domains: mergeArrays(parent.allowed_domains, child.allowed_domains),
3338
+ denied_domains: mergeArrays(parent.denied_domains, child.denied_domains),
3339
+ max_budget_per_session: child.max_budget_per_session ?? parent.max_budget_per_session,
3340
+ max_budget_per_day: child.max_budget_per_day ?? parent.max_budget_per_day,
3341
+ may_spawn: child.may_spawn ?? parent.may_spawn,
3342
+ max_spawn_depth: child.max_spawn_depth ?? parent.max_spawn_depth
3343
+ };
3344
+ }
3345
+ function mergeRules(parentRules, childRules) {
3346
+ const allRules = [...parentRules, ...childRules];
3347
+ return allRules.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
3348
+ }
3349
+ function mergeArrays(parent, child) {
3350
+ const combined = [...parent ?? [], ...child ?? []];
3351
+ return [...new Set(combined)];
3352
+ }
3353
+ function evaluatePolicy(policy, action, resource, context) {
3354
+ for (const rule of policy.rules) {
3355
+ if (ruleMatches(rule, action, resource, context)) {
3356
+ return {
3357
+ allowed: rule.effect === "allow",
3358
+ effect: rule.effect,
3359
+ matchedRule: rule,
3360
+ matched: true,
3361
+ reason: `Rule "${rule.id}" matched: ${rule.description ?? rule.effect}`
3362
+ };
3363
+ }
3364
+ }
3365
+ const defaultEffect = policy.capabilities?.default_effect ?? "deny";
3366
+ return {
3367
+ allowed: defaultEffect === "allow",
3368
+ effect: defaultEffect,
3369
+ matchedRule: void 0,
3370
+ matched: false,
3371
+ reason: `No rule matched, using default effect: ${defaultEffect}`
3372
+ };
3373
+ }
3374
+ function ruleMatches(rule, action, resource, context) {
3375
+ if (!matchesPattern(action, rule.actions)) {
3376
+ return false;
3377
+ }
3378
+ if (!matchesPattern(resource, rule.resources)) {
3379
+ return false;
3380
+ }
3381
+ if (rule.conditions) {
3382
+ if (!evaluateConditions(rule.conditions, context)) {
3383
+ return false;
3384
+ }
3385
+ }
3386
+ return true;
3387
+ }
3388
+ function matchesPattern(value, patterns) {
3389
+ for (const pattern of patterns) {
3390
+ if (pattern === "*") {
3391
+ return true;
3392
+ }
3393
+ if (pattern.endsWith("*")) {
3394
+ const prefix = pattern.slice(0, -1);
3395
+ if (value.startsWith(prefix)) {
3396
+ return true;
3397
+ }
3398
+ } else if (pattern.startsWith("*")) {
3399
+ const suffix = pattern.slice(1);
3400
+ if (value.endsWith(suffix)) {
3401
+ return true;
3402
+ }
3403
+ } else if (pattern === value) {
3404
+ return true;
3405
+ }
3406
+ }
3407
+ return false;
3408
+ }
3409
+ function evaluateConditions(conditions, context) {
3410
+ if (conditions.risk_levels && conditions.risk_levels.length > 0) {
3411
+ if (!conditions.risk_levels.includes(context.riskLevel)) {
3412
+ return false;
3413
+ }
3414
+ }
3415
+ if (conditions.modes && conditions.modes.length > 0) {
3416
+ if (!conditions.modes.includes(context.mode)) {
3417
+ return false;
3418
+ }
3419
+ }
3420
+ if (conditions.time_ranges && conditions.time_ranges.length > 0 && context.timestamp) {
3421
+ const currentTime = new Date(context.timestamp);
3422
+ const timeStr = currentTime.toTimeString().slice(0, 5);
3423
+ const inRange = conditions.time_ranges.some((range) => {
3424
+ return timeStr >= range.start && timeStr <= range.end;
3425
+ });
3426
+ if (!inRange) {
3427
+ return false;
3428
+ }
3429
+ }
3430
+ return true;
3431
+ }
3432
+ function isToolAllowed(tool, capabilities) {
3433
+ if (!capabilities) {
3434
+ return false;
3435
+ }
3436
+ if (capabilities.denied_tools.length > 0 && matchesPattern(tool, capabilities.denied_tools)) {
3437
+ return false;
3438
+ }
3439
+ if (capabilities.allowed_tools.length > 0 && matchesPattern(tool, capabilities.allowed_tools)) {
3440
+ return true;
3441
+ }
3442
+ return capabilities.default_effect === "allow";
3443
+ }
3444
+ function isDomainAllowed(domain, capabilities) {
3445
+ if (!capabilities) {
3446
+ return false;
3447
+ }
3448
+ if (capabilities.denied_domains.length > 0 && matchesDomainPattern(domain, capabilities.denied_domains)) {
3449
+ return false;
3450
+ }
3451
+ if (capabilities.allowed_domains.length > 0 && matchesDomainPattern(domain, capabilities.allowed_domains)) {
3452
+ return true;
3453
+ }
3454
+ return capabilities.default_effect === "allow";
3455
+ }
3456
+ function matchesDomainPattern(domain, patterns) {
3457
+ for (const pattern of patterns) {
3458
+ if (pattern === "*") {
3459
+ return true;
3460
+ }
3461
+ if (pattern.startsWith("*.")) {
3462
+ const suffix = pattern.slice(1);
3463
+ if (domain === pattern.slice(2) || domain.endsWith(suffix)) {
3464
+ return true;
3465
+ }
3466
+ } else if (pattern === domain) {
3467
+ return true;
3468
+ }
3469
+ }
3470
+ return false;
3471
+ }
3472
+ function selectPolicy(criteria, repository, defaultPolicyId) {
3473
+ const candidatePolicies = [];
3474
+ const scoredPolicies = [];
3475
+ const policies = getAllPoliciesFromRepository(repository);
3476
+ for (const [policyId, policy] of policies) {
3477
+ candidatePolicies.push(policyId);
3478
+ const appliesToResult = checkAppliesTo(policy.applies_to, criteria.assetId);
3479
+ if (!appliesToResult.applies) {
3480
+ continue;
3481
+ }
3482
+ const score = scorePolicy(policy, criteria, appliesToResult.isExplicit);
3483
+ const reason = determineSelectionReason(appliesToResult, score);
3484
+ scoredPolicies.push({ policyId, policy, score, reason });
3485
+ }
3486
+ scoredPolicies.sort((a, b) => b.score.total - a.score.total);
3487
+ if (scoredPolicies.length > 0) {
3488
+ const best = scoredPolicies[0];
3489
+ return {
3490
+ policy: best.policy,
3491
+ policyId: best.policyId,
3492
+ selectionReason: best.reason,
3493
+ candidatePolicies,
3494
+ score: best.score
3495
+ };
3496
+ }
3497
+ if (defaultPolicyId && repository.has(defaultPolicyId)) {
3498
+ const defaultPolicy = repository.get(defaultPolicyId);
3499
+ if (defaultPolicy) {
3500
+ return {
3501
+ policy: defaultPolicy,
3502
+ policyId: defaultPolicyId,
3503
+ selectionReason: "default_policy",
3504
+ candidatePolicies
3505
+ };
3506
+ }
3507
+ }
3508
+ return {
3509
+ policy: null,
3510
+ policyId: null,
3511
+ selectionReason: "no_policy_found",
3512
+ candidatePolicies
3513
+ };
3514
+ }
3515
+ function getAllPoliciesFromRepository(repository) {
3516
+ if (repository instanceof Map) {
3517
+ return repository;
3518
+ }
3519
+ const result = /* @__PURE__ */ new Map();
3520
+ const anyRepo = repository;
3521
+ if (anyRepo.policies instanceof Map) {
3522
+ return anyRepo.policies;
3523
+ }
3524
+ return result;
3525
+ }
3526
+ function checkAppliesTo(appliesTo, assetId) {
3527
+ for (const pattern of appliesTo) {
3528
+ if (pattern === "*") {
3529
+ return { applies: true, isExplicit: false };
3530
+ }
3531
+ if (pattern === assetId) {
3532
+ return { applies: true, isExplicit: true };
3533
+ }
3534
+ if (pattern.endsWith("*") && assetId.startsWith(pattern.slice(0, -1))) {
3535
+ return { applies: true, isExplicit: false };
3536
+ }
3537
+ }
3538
+ return { applies: false, isExplicit: false };
3539
+ }
3540
+ function scorePolicy(policy, criteria, isExplicitMatch) {
3541
+ let total = 0;
3542
+ let explicitMatch = 0;
3543
+ let riskLevelMatch = 0;
3544
+ let tagMatches = 0;
3545
+ if (isExplicitMatch) {
3546
+ explicitMatch = 100;
3547
+ total += 100;
3548
+ }
3549
+ const hasRiskLevelRule = policy.rules.some(
3550
+ (rule) => rule.conditions?.risk_levels?.includes(criteria.riskLevel)
3551
+ );
3552
+ if (hasRiskLevelRule) {
3553
+ riskLevelMatch = 50;
3554
+ total += 50;
3555
+ }
3556
+ const policyTags = policy.metadata?.tags ?? [];
3557
+ const criteriaTags = criteria.tags ?? [];
3558
+ for (const tag of criteriaTags) {
3559
+ if (policyTags.includes(tag)) {
3560
+ tagMatches++;
3561
+ total += 10;
3562
+ }
3563
+ }
3564
+ const maxPriority = Math.max(...policy.rules.map((r) => r.priority ?? 0), 0);
3565
+ total += maxPriority;
3566
+ return {
3567
+ total,
3568
+ explicitMatch,
3569
+ riskLevelMatch,
3570
+ tagMatches,
3571
+ priority: maxPriority
3572
+ };
3573
+ }
3574
+ function determineSelectionReason(appliesToResult, score) {
3575
+ if (appliesToResult.isExplicit) {
3576
+ return "explicit_match";
3577
+ }
3578
+ if (score.riskLevelMatch > 0) {
3579
+ return "risk_level_match";
3580
+ }
3581
+ if (score.tagMatches > 0) {
3582
+ return "tag_match";
3583
+ }
3584
+ return "wildcard_match";
3585
+ }
3586
+ function createPolicySelector(repository, defaultPolicyId, cacheSize = 100) {
3587
+ const cache = /* @__PURE__ */ new Map();
3588
+ let hits = 0;
3589
+ let misses = 0;
3590
+ function getCacheKey(criteria) {
3591
+ return `${criteria.assetId}|${criteria.riskLevel}|${criteria.mode}|${(criteria.tags ?? []).sort().join(",")}|${criteria.environment ?? ""}`;
3592
+ }
3593
+ function select(criteria) {
3594
+ const key = getCacheKey(criteria);
3595
+ if (cache.has(key)) {
3596
+ hits++;
3597
+ return cache.get(key);
3598
+ }
3599
+ misses++;
3600
+ const result = selectPolicy(criteria, repository, defaultPolicyId);
3601
+ if (cache.size >= cacheSize) {
3602
+ const firstKey = cache.keys().next().value;
3603
+ if (firstKey) {
3604
+ cache.delete(firstKey);
3605
+ }
3606
+ }
3607
+ cache.set(key, result);
3608
+ return result;
3609
+ }
3610
+ return {
3611
+ select,
3612
+ clearCache: () => cache.clear(),
3613
+ getCacheStats: () => ({ hits, misses, size: cache.size })
3614
+ };
3615
+ }
3616
+
3617
+ // src/air/index.ts
3618
+ var import_zod3 = require("zod");
3619
+ var AIRVendorSchema = import_zod3.z.object({
3620
+ /** Vendor identifier (e.g., "openai", "anthropic", "google") */
3621
+ id: import_zod3.z.string().min(1),
3622
+ /** Human-readable vendor name */
3623
+ name: import_zod3.z.string().optional(),
3624
+ /** Status of this vendor */
3625
+ status: import_zod3.z.enum(["approved", "pending", "blocked"]).default("pending"),
3626
+ /** Optional approval ticket ID (Golden Thread) */
3627
+ approval_ticket: import_zod3.z.string().optional(),
3628
+ /** When approval was granted */
3629
+ approved_at: import_zod3.z.string().datetime().optional(),
3630
+ /** Who approved this vendor */
3631
+ approved_by: import_zod3.z.string().email().optional(),
3632
+ /** Expiration date for approval */
3633
+ expires_at: import_zod3.z.string().datetime().optional(),
3634
+ /** Vendor-specific notes */
3635
+ notes: import_zod3.z.string().optional()
3636
+ });
3637
+ var AIRModelSchema = import_zod3.z.object({
3638
+ /** Model identifier (e.g., "gpt-4", "claude-3-opus") */
3639
+ id: import_zod3.z.string().min(1),
3640
+ /** Vendor that provides this model */
3641
+ vendor_id: import_zod3.z.string().min(1),
3642
+ /** Human-readable model name */
3643
+ name: import_zod3.z.string().optional(),
3644
+ /** Model version pattern (supports wildcards like "gpt-4*") */
3645
+ version_pattern: import_zod3.z.string().optional(),
3646
+ /** Status of this model */
3647
+ status: import_zod3.z.enum(["approved", "pending", "blocked"]).default("pending"),
3648
+ /** Maximum allowed parameters (for on-premise deployment considerations) */
3649
+ max_parameters: import_zod3.z.number().positive().optional(),
3650
+ /** Risk level assigned to this model */
3651
+ risk_level: import_zod3.z.enum(["minimal", "limited", "high", "unacceptable"]).optional(),
3652
+ /** Optional approval ticket ID */
3653
+ approval_ticket: import_zod3.z.string().optional(),
3654
+ /** When approval was granted */
3655
+ approved_at: import_zod3.z.string().datetime().optional(),
3656
+ /** Expiration date for approval */
3657
+ expires_at: import_zod3.z.string().datetime().optional(),
3658
+ /** Model-specific notes */
3659
+ notes: import_zod3.z.string().optional()
3660
+ });
3661
+ var AIRRegionSchema = import_zod3.z.object({
3662
+ /** Region code (e.g., "us-east-1", "eu-west-1", "EU", "US") */
3663
+ code: import_zod3.z.string().min(1),
3664
+ /** Human-readable region name */
3665
+ name: import_zod3.z.string().optional(),
3666
+ /** Status of this region */
3667
+ status: import_zod3.z.enum(["allowed", "restricted", "blocked"]).default("allowed"),
3668
+ /** Jurisdictions this region falls under (e.g., ["GDPR", "EU-AI-ACT"]) */
3669
+ jurisdictions: import_zod3.z.array(import_zod3.z.string()).default([]),
3670
+ /** Data residency requirements */
3671
+ data_residency: import_zod3.z.enum(["required", "preferred", "none"]).default("none"),
3672
+ /** Notes about this region */
3673
+ notes: import_zod3.z.string().optional()
3674
+ });
3675
+ var AIRRegistryConstraintsSchema = import_zod3.z.object({
3676
+ /** List of approved vendors */
3677
+ allowed_vendors: import_zod3.z.array(AIRVendorSchema).default([]),
3678
+ /** List of blocked vendors */
3679
+ blocked_vendors: import_zod3.z.array(import_zod3.z.string()).default([]),
3680
+ /** List of approved regions */
3681
+ allowed_regions: import_zod3.z.array(AIRRegionSchema).default([]),
3682
+ /** List of blocked regions */
3683
+ blocked_regions: import_zod3.z.array(import_zod3.z.string()).default([]),
3684
+ /** List of approved models */
3685
+ allowed_models: import_zod3.z.array(AIRModelSchema).default([]),
3686
+ /** List of blocked models (patterns supported) */
3687
+ blocked_models: import_zod3.z.array(import_zod3.z.string()).default([]),
3688
+ /** Maximum model parameters allowed */
3689
+ max_model_parameters: import_zod3.z.number().positive().optional(),
3690
+ /** Require vendor approval before use */
3691
+ require_vendor_approval: import_zod3.z.boolean().default(true),
3692
+ /** Require model approval before use */
3693
+ require_model_approval: import_zod3.z.boolean().default(true),
3694
+ /** Default behavior for unknown vendors: "block" or "request_approval" */
3695
+ unknown_vendor_behavior: import_zod3.z.enum(["block", "request_approval"]).default("request_approval"),
3696
+ /** Default behavior for unknown models */
3697
+ unknown_model_behavior: import_zod3.z.enum(["block", "request_approval"]).default("request_approval")
3698
+ });
3699
+ var AIRPIIFilterConfigSchema = import_zod3.z.object({
3700
+ /** Whether PII filtering is enabled */
3701
+ enabled: import_zod3.z.boolean().default(false),
3702
+ /** PII types to filter (e.g., ["email", "phone", "ssn", "credit_card"]) */
3703
+ filter_types: import_zod3.z.array(import_zod3.z.string()).default([]),
3704
+ /** Action when PII is detected: "redact", "block", "warn", "audit" */
3705
+ action: import_zod3.z.enum(["redact", "block", "warn", "audit"]).default("warn"),
3706
+ /** Custom patterns to detect (regex) */
3707
+ custom_patterns: import_zod3.z.array(import_zod3.z.object({
3708
+ name: import_zod3.z.string(),
3709
+ pattern: import_zod3.z.string(),
3710
+ action: import_zod3.z.enum(["redact", "block", "warn", "audit"]).optional()
3711
+ })).default([])
3712
+ });
3713
+ var AIRToxicityFilterConfigSchema = import_zod3.z.object({
3714
+ /** Whether toxicity filtering is enabled */
3715
+ enabled: import_zod3.z.boolean().default(false),
3716
+ /** Toxicity threshold (0-1) */
3717
+ threshold: import_zod3.z.number().min(0).max(1).default(0.7),
3718
+ /** Categories to filter (e.g., ["hate", "violence", "sexual"]) */
3719
+ categories: import_zod3.z.array(import_zod3.z.string()).default([]),
3720
+ /** Action when toxicity is detected */
3721
+ action: import_zod3.z.enum(["block", "warn", "audit"]).default("warn")
3722
+ });
3723
+ var AIRRuntimeConstraintsSchema = import_zod3.z.object({
3724
+ /** PII filtering configuration */
3725
+ pii_filter: AIRPIIFilterConfigSchema.optional(),
3726
+ /** Toxicity filtering configuration */
3727
+ toxicity_filter: AIRToxicityFilterConfigSchema.optional(),
3728
+ /** Data retention period in days (0 = no retention) */
3729
+ data_retention_days: import_zod3.z.number().int().min(0).default(90),
3730
+ /** Whether to enable output watermarking */
3731
+ watermark_enabled: import_zod3.z.boolean().default(false),
3732
+ /** Logging level: "none", "errors", "all" */
3733
+ logging_level: import_zod3.z.enum(["none", "errors", "all"]).default("all"),
3734
+ /** Maximum tokens per request */
3735
+ max_tokens_per_request: import_zod3.z.number().int().positive().optional(),
3736
+ /** Maximum requests per minute */
3737
+ max_requests_per_minute: import_zod3.z.number().int().positive().optional(),
3738
+ /** Maximum cost per request in USD */
3739
+ max_cost_per_request_usd: import_zod3.z.number().positive().optional(),
3740
+ /** Maximum cost per day in USD */
3741
+ max_cost_per_day_usd: import_zod3.z.number().positive().optional(),
3742
+ /** Session timeout in seconds */
3743
+ session_timeout_seconds: import_zod3.z.number().int().positive().optional(),
3744
+ /** Require human approval for specific actions */
3745
+ human_approval_required: import_zod3.z.array(import_zod3.z.string()).default([]),
3746
+ /** Kill switch configuration */
3747
+ kill_switch: import_zod3.z.object({
3748
+ enabled: import_zod3.z.boolean().default(true),
3749
+ channel: import_zod3.z.enum(["sse", "polling", "file"]).default("sse"),
3750
+ poll_interval_ms: import_zod3.z.number().int().positive().default(5e3)
3751
+ }).optional(),
3752
+ /** Grounding check configuration (prevent hallucination) */
3753
+ grounding_check: import_zod3.z.object({
3754
+ enabled: import_zod3.z.boolean().default(false),
3755
+ confidence_threshold: import_zod3.z.number().min(0).max(1).default(0.8),
3756
+ action: import_zod3.z.enum(["block", "warn", "audit"]).default("warn")
3757
+ }).optional()
3758
+ });
3759
+ var AIRBuildConstraintsSchema = import_zod3.z.object({
3760
+ /** Require Golden Thread linkage (business justification) */
3761
+ require_golden_thread: import_zod3.z.boolean().default(true),
3762
+ /** Require asset card for all AI assets */
3763
+ require_asset_card: import_zod3.z.boolean().default(true),
3764
+ /** Require risk classification */
3765
+ require_risk_classification: import_zod3.z.boolean().default(true),
3766
+ /** Require model card documentation */
3767
+ require_model_card: import_zod3.z.boolean().default(false),
3768
+ /** Require security review for high-risk assets */
3769
+ require_security_review: import_zod3.z.boolean().default(false),
3770
+ /** Minimum risk levels that require security review */
3771
+ security_review_risk_levels: import_zod3.z.array(import_zod3.z.enum(["high", "unacceptable"])).default(["high", "unacceptable"]),
3772
+ /** Require governance.lock file */
3773
+ require_governance_lock: import_zod3.z.boolean().default(true),
3774
+ /** governance.lock must be signed */
3775
+ require_lock_signature: import_zod3.z.boolean().default(false),
3776
+ /** Block merge on validation failure */
3777
+ block_on_failure: import_zod3.z.boolean().default(true),
3778
+ /** Generate SARIF report for GitHub Security tab */
3779
+ generate_sarif: import_zod3.z.boolean().default(true),
3780
+ /** Required approvals before deployment */
3781
+ required_approvals: import_zod3.z.array(import_zod3.z.object({
3782
+ role: import_zod3.z.string(),
3783
+ count: import_zod3.z.number().int().positive().default(1)
3784
+ })).default([]),
3785
+ /** Allowed deployment environments */
3786
+ allowed_environments: import_zod3.z.array(import_zod3.z.string()).default(["development", "staging", "production"]),
3787
+ /** Environment-specific constraints */
3788
+ environment_constraints: import_zod3.z.record(import_zod3.z.object({
3789
+ require_approval: import_zod3.z.boolean().default(false),
3790
+ approvers: import_zod3.z.array(import_zod3.z.string()).default([]),
3791
+ require_testing: import_zod3.z.boolean().default(false),
3792
+ test_coverage_threshold: import_zod3.z.number().min(0).max(100).optional()
3793
+ })).optional()
3794
+ });
3795
+ var AIRPolicySourceSchema = import_zod3.z.object({
3796
+ /** Unique identifier for this source */
3797
+ id: import_zod3.z.string().min(1),
3798
+ /** Type of source: "pdf", "url", "confluence", "jira", "manual" */
3799
+ type: import_zod3.z.enum(["pdf", "url", "confluence", "jira", "manual"]),
3800
+ /** URI to the source document */
3801
+ uri: import_zod3.z.string(),
3802
+ /** SHA-256 hash of the source content */
3803
+ content_hash: import_zod3.z.string().regex(/^sha256:[a-f0-9]{64}$/),
3804
+ /** When the source was last fetched */
3805
+ fetched_at: import_zod3.z.string().datetime(),
3806
+ /** Title of the policy document */
3807
+ title: import_zod3.z.string().optional(),
3808
+ /** Version of the policy document */
3809
+ version: import_zod3.z.string().optional(),
3810
+ /** Confidence score of extraction (0-1) */
3811
+ extraction_confidence: import_zod3.z.number().min(0).max(1).optional()
3812
+ });
3813
+ var AIRMetadataSchema = import_zod3.z.object({
3814
+ /** When this AIR was generated */
3815
+ generated_at: import_zod3.z.string().datetime(),
3816
+ /** Tool/system that generated this AIR */
3817
+ generated_by: import_zod3.z.string().default("aigrc-policy-compiler"),
3818
+ /** Version of the policy compiler */
3819
+ compiler_version: import_zod3.z.string(),
3820
+ /** Organization this AIR belongs to */
3821
+ organization: import_zod3.z.string().optional(),
3822
+ /** Environment this AIR is for (e.g., "production", "staging") */
3823
+ environment: import_zod3.z.string().optional(),
3824
+ /** Human-readable description */
3825
+ description: import_zod3.z.string().optional(),
3826
+ /** Tags for categorization */
3827
+ tags: import_zod3.z.array(import_zod3.z.string()).default([]),
3828
+ /** Custom metadata fields */
3829
+ custom: import_zod3.z.record(import_zod3.z.unknown()).optional()
3830
+ });
3831
+ var AIRSchema = import_zod3.z.object({
3832
+ /** Schema version for forward compatibility */
3833
+ version: import_zod3.z.literal("1.0"),
3834
+ /** Unique identifier for this AIR */
3835
+ id: import_zod3.z.string().uuid(),
3836
+ /** Human-readable name */
3837
+ name: import_zod3.z.string().min(1).max(200),
3838
+ /** SHA-256 hash of this AIR (computed after serialization) */
3839
+ hash: import_zod3.z.string().regex(/^sha256:[a-f0-9]{64}$/).optional(),
3840
+ /** Policy sources that contributed to this AIR */
3841
+ policy_sources: import_zod3.z.array(AIRPolicySourceSchema).default([]),
3842
+ /** Registry constraints (vendor/model/region governance) */
3843
+ registry: AIRRegistryConstraintsSchema.default({}),
3844
+ /** Runtime constraints (execution-time governance) */
3845
+ runtime: AIRRuntimeConstraintsSchema.default({}),
3846
+ /** Build constraints (CI/CD governance) */
3847
+ build: AIRBuildConstraintsSchema.default({}),
3848
+ /** Metadata about this AIR */
3849
+ metadata: AIRMetadataSchema,
3850
+ /** When this AIR expires (forces re-compilation) */
3851
+ expires_at: import_zod3.z.string().datetime().optional(),
3852
+ /** Digital signatures for verification */
3853
+ signatures: import_zod3.z.array(import_zod3.z.object({
3854
+ /** Signer identity (email or system ID) */
3855
+ signer: import_zod3.z.string(),
3856
+ /** Algorithm used (RS256, ES256) */
3857
+ algorithm: import_zod3.z.enum(["RS256", "ES256"]),
3858
+ /** Base64-encoded signature */
3859
+ signature: import_zod3.z.string(),
3860
+ /** When the signature was created */
3861
+ signed_at: import_zod3.z.string().datetime(),
3862
+ /** Key ID for verification */
3863
+ key_id: import_zod3.z.string().optional()
3864
+ })).default([])
3865
+ });
3866
+ function createEmptyAIR(name, compilerVersion = "1.0.0") {
3867
+ return {
3868
+ version: "1.0",
3869
+ id: crypto.randomUUID(),
3870
+ name,
3871
+ policy_sources: [],
3872
+ registry: {
3873
+ allowed_vendors: [],
3874
+ blocked_vendors: [],
3875
+ allowed_regions: [],
3876
+ blocked_regions: [],
3877
+ allowed_models: [],
3878
+ blocked_models: [],
3879
+ require_vendor_approval: true,
3880
+ require_model_approval: true,
3881
+ unknown_vendor_behavior: "request_approval",
3882
+ unknown_model_behavior: "request_approval"
3883
+ },
3884
+ runtime: {
3885
+ data_retention_days: 90,
3886
+ watermark_enabled: false,
3887
+ logging_level: "all",
3888
+ human_approval_required: []
3889
+ },
3890
+ build: {
3891
+ require_golden_thread: true,
3892
+ require_asset_card: true,
3893
+ require_risk_classification: true,
3894
+ require_model_card: false,
3895
+ require_security_review: false,
3896
+ security_review_risk_levels: ["high", "unacceptable"],
3897
+ require_governance_lock: true,
3898
+ require_lock_signature: false,
3899
+ block_on_failure: true,
3900
+ generate_sarif: true,
3901
+ required_approvals: [],
3902
+ allowed_environments: ["development", "staging", "production"]
3903
+ },
3904
+ metadata: {
3905
+ generated_at: (/* @__PURE__ */ new Date()).toISOString(),
3906
+ generated_by: "aigrc-policy-compiler",
3907
+ compiler_version: compilerVersion,
3908
+ tags: []
3909
+ },
3910
+ signatures: []
3911
+ };
3912
+ }
3913
+ function validateAIR(air) {
3914
+ const result = AIRSchema.safeParse(air);
3915
+ if (result.success) {
3916
+ return { valid: true, errors: [] };
3917
+ }
3918
+ return {
3919
+ valid: false,
3920
+ errors: result.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`)
3921
+ };
3922
+ }
3923
+ function isVendorAllowed(vendorId, registry2) {
3924
+ if (registry2.blocked_vendors.includes(vendorId)) {
3925
+ return { allowed: false, reason: "Vendor is blocked", requiresApproval: false };
3926
+ }
3927
+ const allowedVendor = registry2.allowed_vendors.find((v) => v.id === vendorId);
3928
+ if (allowedVendor) {
3929
+ if (allowedVendor.status === "approved") {
3930
+ if (allowedVendor.expires_at && new Date(allowedVendor.expires_at) < /* @__PURE__ */ new Date()) {
3931
+ return { allowed: false, reason: "Vendor approval has expired", requiresApproval: true };
3932
+ }
3933
+ return { allowed: true, reason: "Vendor is approved", requiresApproval: false };
3934
+ }
3935
+ if (allowedVendor.status === "pending") {
3936
+ return { allowed: false, reason: "Vendor approval is pending", requiresApproval: true };
3937
+ }
3938
+ return { allowed: false, reason: "Vendor is blocked", requiresApproval: false };
3939
+ }
3940
+ if (registry2.unknown_vendor_behavior === "block") {
3941
+ return { allowed: false, reason: "Unknown vendor (blocked by policy)", requiresApproval: false };
3942
+ }
3943
+ return { allowed: false, reason: "Unknown vendor (requires approval)", requiresApproval: true };
3944
+ }
3945
+ function isModelAllowed(modelId, vendorId, registry2) {
3946
+ for (const pattern of registry2.blocked_models) {
3947
+ if (matchesPattern2(modelId, pattern)) {
3948
+ return { allowed: false, reason: `Model matches blocked pattern: ${pattern}`, requiresApproval: false };
3949
+ }
3950
+ }
3951
+ const allowedModel = registry2.allowed_models.find(
3952
+ (m) => m.id === modelId && m.vendor_id === vendorId
3953
+ );
3954
+ if (allowedModel) {
3955
+ if (allowedModel.status === "approved") {
3956
+ if (allowedModel.expires_at && new Date(allowedModel.expires_at) < /* @__PURE__ */ new Date()) {
3957
+ return { allowed: false, reason: "Model approval has expired", requiresApproval: true };
3958
+ }
3959
+ return { allowed: true, reason: "Model is approved", requiresApproval: false };
3960
+ }
3961
+ if (allowedModel.status === "pending") {
3962
+ return { allowed: false, reason: "Model approval is pending", requiresApproval: true };
3963
+ }
3964
+ return { allowed: false, reason: "Model is blocked", requiresApproval: false };
3965
+ }
3966
+ const matchingModel = registry2.allowed_models.find(
3967
+ (m) => m.vendor_id === vendorId && m.version_pattern && matchesPattern2(modelId, m.version_pattern)
3968
+ );
3969
+ if (matchingModel && matchingModel.status === "approved") {
3970
+ return { allowed: true, reason: `Model matches approved pattern: ${matchingModel.version_pattern}`, requiresApproval: false };
3971
+ }
3972
+ if (registry2.unknown_model_behavior === "block") {
3973
+ return { allowed: false, reason: "Unknown model (blocked by policy)", requiresApproval: false };
3974
+ }
3975
+ return { allowed: false, reason: "Unknown model (requires approval)", requiresApproval: true };
3976
+ }
3977
+ function isRegionAllowed(regionCode, registry2) {
3978
+ if (registry2.blocked_regions.includes(regionCode)) {
3979
+ return { allowed: false, reason: "Region is blocked", dataResidency: "none" };
3980
+ }
3981
+ const allowedRegion = registry2.allowed_regions.find((r) => r.code === regionCode);
3982
+ if (allowedRegion) {
3983
+ if (allowedRegion.status === "blocked") {
3984
+ return { allowed: false, reason: "Region is blocked", dataResidency: "none" };
3985
+ }
3986
+ if (allowedRegion.status === "restricted") {
3987
+ return { allowed: true, reason: "Region is restricted (requires approval)", dataResidency: allowedRegion.data_residency };
3988
+ }
3989
+ return { allowed: true, reason: "Region is allowed", dataResidency: allowedRegion.data_residency };
3990
+ }
3991
+ if (registry2.allowed_regions.length === 0) {
3992
+ return { allowed: true, reason: "No region restrictions", dataResidency: "none" };
3993
+ }
3994
+ return { allowed: false, reason: "Region not in allowed list", dataResidency: "none" };
3995
+ }
3996
+ function matchesPattern2(value, pattern) {
3997
+ if (pattern === "*") {
3998
+ return true;
3999
+ }
4000
+ if (pattern.endsWith("*")) {
4001
+ return value.startsWith(pattern.slice(0, -1));
4002
+ }
4003
+ if (pattern.startsWith("*")) {
4004
+ return value.endsWith(pattern.slice(1));
4005
+ }
4006
+ return value === pattern;
4007
+ }
4008
+
4009
+ // src/governance-lock/index.ts
4010
+ var import_zod4 = require("zod");
4011
+ var yaml2 = __toESM(require("yaml"));
4012
+ var GovernanceLockSignatureSchema = import_zod4.z.object({
4013
+ /** Signer identity (email or system ID) */
4014
+ signer: import_zod4.z.string().min(1),
4015
+ /** Role of the signer (e.g., "CISO", "PolicyOwner", "SecurityLead") */
4016
+ role: import_zod4.z.string().optional(),
4017
+ /** Algorithm used: RS256 (RSA-SHA256) or ES256 (ECDSA-P256) */
4018
+ algorithm: import_zod4.z.enum(["RS256", "ES256"]),
4019
+ /** Base64-encoded signature */
4020
+ signature: import_zod4.z.string().min(1),
4021
+ /** When the signature was created */
4022
+ signed_at: import_zod4.z.string().datetime(),
4023
+ /** Key ID for key rotation support */
4024
+ key_id: import_zod4.z.string().optional(),
4025
+ /** Expiration of this signature (optional, separate from lock expiration) */
4026
+ expires_at: import_zod4.z.string().datetime().optional(),
4027
+ /** Certificate chain for verification (optional) */
4028
+ certificate_chain: import_zod4.z.array(import_zod4.z.string()).optional()
4029
+ });
4030
+ var GovernanceLockPolicySourceSchema = import_zod4.z.object({
4031
+ /** Unique identifier for this source */
4032
+ id: import_zod4.z.string().min(1),
4033
+ /** Type of source */
4034
+ type: import_zod4.z.enum(["pdf", "url", "confluence", "jira", "manual"]),
4035
+ /** URI to the source document */
4036
+ uri: import_zod4.z.string(),
4037
+ /** SHA-256 hash of the source content at time of compilation */
4038
+ content_hash: import_zod4.z.string().regex(/^sha256:[a-f0-9]{64}$/),
4039
+ /** When the source was fetched */
4040
+ fetched_at: import_zod4.z.string().datetime(),
4041
+ /** Title of the policy document */
4042
+ title: import_zod4.z.string().optional(),
4043
+ /** Version of the policy document */
4044
+ version: import_zod4.z.string().optional()
4045
+ });
4046
+ var GovernanceLockRegistryConstraintsSchema = import_zod4.z.object({
4047
+ /** List of approved vendor IDs */
4048
+ allowed_vendor_ids: import_zod4.z.array(import_zod4.z.string()).default([]),
4049
+ /** List of blocked vendor IDs */
4050
+ blocked_vendor_ids: import_zod4.z.array(import_zod4.z.string()).default([]),
4051
+ /** List of approved region codes */
4052
+ allowed_region_codes: import_zod4.z.array(import_zod4.z.string()).default([]),
4053
+ /** List of blocked region codes */
4054
+ blocked_region_codes: import_zod4.z.array(import_zod4.z.string()).default([]),
4055
+ /** List of approved model patterns */
4056
+ allowed_model_patterns: import_zod4.z.array(import_zod4.z.string()).default([]),
4057
+ /** List of blocked model patterns */
4058
+ blocked_model_patterns: import_zod4.z.array(import_zod4.z.string()).default([]),
4059
+ /** Maximum model parameters allowed */
4060
+ max_model_parameters: import_zod4.z.number().positive().optional()
4061
+ });
4062
+ var GovernanceLockRuntimeConstraintsSchema = import_zod4.z.object({
4063
+ /** Whether PII filtering is required */
4064
+ pii_filter_enabled: import_zod4.z.boolean().default(false),
4065
+ /** PII filter action */
4066
+ pii_filter_action: import_zod4.z.enum(["redact", "block", "warn", "audit"]).optional(),
4067
+ /** Whether toxicity filtering is required */
4068
+ toxicity_filter_enabled: import_zod4.z.boolean().default(false),
4069
+ /** Toxicity threshold */
4070
+ toxicity_threshold: import_zod4.z.number().min(0).max(1).optional(),
4071
+ /** Data retention period in days */
4072
+ data_retention_days: import_zod4.z.number().int().min(0).default(90),
4073
+ /** Whether watermarking is required */
4074
+ watermark_enabled: import_zod4.z.boolean().default(false),
4075
+ /** Logging level */
4076
+ logging_level: import_zod4.z.enum(["none", "errors", "all"]).default("all"),
4077
+ /** Maximum tokens per request */
4078
+ max_tokens_per_request: import_zod4.z.number().int().positive().optional(),
4079
+ /** Maximum cost per day in USD */
4080
+ max_cost_per_day_usd: import_zod4.z.number().positive().optional(),
4081
+ /** Kill switch enabled */
4082
+ kill_switch_enabled: import_zod4.z.boolean().default(true)
4083
+ });
4084
+ var GovernanceLockBuildConstraintsSchema = import_zod4.z.object({
4085
+ /** Require Golden Thread linkage */
4086
+ require_golden_thread: import_zod4.z.boolean().default(true),
4087
+ /** Require asset card */
4088
+ require_asset_card: import_zod4.z.boolean().default(true),
4089
+ /** Require risk classification */
4090
+ require_risk_classification: import_zod4.z.boolean().default(true),
4091
+ /** Require model card */
4092
+ require_model_card: import_zod4.z.boolean().default(false),
4093
+ /** Require security review for high risk */
4094
+ require_security_review: import_zod4.z.boolean().default(false),
4095
+ /** Block merge on validation failure */
4096
+ block_on_failure: import_zod4.z.boolean().default(true),
4097
+ /** Generate SARIF report */
4098
+ generate_sarif: import_zod4.z.boolean().default(true),
4099
+ /** Allowed environments */
4100
+ allowed_environments: import_zod4.z.array(import_zod4.z.string()).default(["development", "staging", "production"])
4101
+ });
4102
+ var GovernanceLockConstraintsSchema = import_zod4.z.object({
4103
+ /** Registry constraints (vendor/model/region) */
4104
+ registry: GovernanceLockRegistryConstraintsSchema.default({}),
4105
+ /** Runtime constraints */
4106
+ runtime: GovernanceLockRuntimeConstraintsSchema.default({}),
4107
+ /** Build constraints */
4108
+ build: GovernanceLockBuildConstraintsSchema.default({})
4109
+ });
4110
+ var GovernanceLockSchema = import_zod4.z.object({
4111
+ /** Schema version for forward compatibility */
4112
+ version: import_zod4.z.literal("1.0"),
4113
+ /** When this lock file was generated */
4114
+ generated_at: import_zod4.z.string().datetime(),
4115
+ /** SHA-256 hash of the compiled policy (AIR) */
4116
+ policy_hash: import_zod4.z.string().regex(/^sha256:[a-f0-9]{64}$/),
4117
+ /** Name of this policy lock */
4118
+ name: import_zod4.z.string().min(1).max(200).optional(),
4119
+ /** Description of this lock file */
4120
+ description: import_zod4.z.string().max(500).optional(),
4121
+ /** Policy sources that contributed to this lock */
4122
+ policy_sources: import_zod4.z.array(GovernanceLockPolicySourceSchema).default([]),
4123
+ /** Compiled constraints (subset of AIR) */
4124
+ constraints: GovernanceLockConstraintsSchema.default({}),
4125
+ /** Digital signatures from policy owners */
4126
+ signatures: import_zod4.z.array(GovernanceLockSignatureSchema).default([]),
4127
+ /** When this lock file expires (forces re-compilation) */
4128
+ expires_at: import_zod4.z.string().datetime(),
4129
+ /** Tool/system that generated this lock */
4130
+ generated_by: import_zod4.z.string().default("aigrc-policy-compiler"),
4131
+ /** Version of the generator */
4132
+ generator_version: import_zod4.z.string().default("1.0.0"),
4133
+ /** Organization this lock belongs to */
4134
+ organization: import_zod4.z.string().optional(),
4135
+ /** Environment this lock is for */
4136
+ environment: import_zod4.z.string().optional(),
4137
+ /** Reference to the full AIR document (optional) */
4138
+ air_reference: import_zod4.z.object({
4139
+ /** AIR document ID */
4140
+ id: import_zod4.z.string().uuid(),
4141
+ /** AIR document location (URI) */
4142
+ location: import_zod4.z.string().optional(),
4143
+ /** AIR document hash */
4144
+ hash: import_zod4.z.string().regex(/^sha256:[a-f0-9]{64}$/)
4145
+ }).optional(),
4146
+ /** Custom metadata fields */
4147
+ metadata: import_zod4.z.record(import_zod4.z.unknown()).optional()
4148
+ });
4149
+ async function computeHash(data) {
4150
+ const encoder = new TextEncoder();
4151
+ const dataBuffer = encoder.encode(data);
4152
+ const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer);
4153
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
4154
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
4155
+ return `sha256:${hashHex}`;
4156
+ }
4157
+ async function createGovernanceLock(air, options = {}) {
4158
+ const now = /* @__PURE__ */ new Date();
4159
+ const expiresAt = new Date(now);
4160
+ expiresAt.setDate(expiresAt.getDate() + (options.expiresInDays ?? 30));
4161
+ const airForHashing = { ...air, signatures: [] };
4162
+ const policyHash = await computeHash(JSON.stringify(airForHashing));
4163
+ const constraints = {
4164
+ registry: {
4165
+ allowed_vendor_ids: air.registry.allowed_vendors.map((v) => v.id),
4166
+ blocked_vendor_ids: air.registry.blocked_vendors,
4167
+ allowed_region_codes: air.registry.allowed_regions.map((r) => r.code),
4168
+ blocked_region_codes: air.registry.blocked_regions,
4169
+ allowed_model_patterns: air.registry.allowed_models.map((m) => m.version_pattern ?? m.id),
4170
+ blocked_model_patterns: air.registry.blocked_models,
4171
+ max_model_parameters: air.registry.max_model_parameters
4172
+ },
4173
+ runtime: {
4174
+ pii_filter_enabled: air.runtime.pii_filter?.enabled ?? false,
4175
+ pii_filter_action: air.runtime.pii_filter?.action,
4176
+ toxicity_filter_enabled: air.runtime.toxicity_filter?.enabled ?? false,
4177
+ toxicity_threshold: air.runtime.toxicity_filter?.threshold,
4178
+ data_retention_days: air.runtime.data_retention_days,
4179
+ watermark_enabled: air.runtime.watermark_enabled,
4180
+ logging_level: air.runtime.logging_level,
4181
+ max_tokens_per_request: air.runtime.max_tokens_per_request,
4182
+ max_cost_per_day_usd: air.runtime.max_cost_per_day_usd,
4183
+ kill_switch_enabled: air.runtime.kill_switch?.enabled ?? true
4184
+ },
4185
+ build: {
4186
+ require_golden_thread: air.build.require_golden_thread,
4187
+ require_asset_card: air.build.require_asset_card,
4188
+ require_risk_classification: air.build.require_risk_classification,
4189
+ require_model_card: air.build.require_model_card,
4190
+ require_security_review: air.build.require_security_review,
4191
+ block_on_failure: air.build.block_on_failure,
4192
+ generate_sarif: air.build.generate_sarif,
4193
+ allowed_environments: air.build.allowed_environments
4194
+ }
4195
+ };
4196
+ const policySources = air.policy_sources.map((s) => ({
4197
+ id: s.id,
4198
+ type: s.type,
4199
+ uri: s.uri,
4200
+ content_hash: s.content_hash,
4201
+ fetched_at: s.fetched_at,
4202
+ title: s.title,
4203
+ version: s.version
4204
+ }));
4205
+ return {
4206
+ version: "1.0",
4207
+ generated_at: now.toISOString(),
4208
+ policy_hash: policyHash,
4209
+ name: options.name ?? air.name,
4210
+ description: options.description,
4211
+ policy_sources: policySources,
4212
+ constraints,
4213
+ signatures: [],
4214
+ expires_at: expiresAt.toISOString(),
4215
+ generated_by: air.metadata.generated_by,
4216
+ generator_version: air.metadata.compiler_version,
4217
+ organization: options.organization ?? air.metadata.organization,
4218
+ environment: options.environment ?? air.metadata.environment,
4219
+ air_reference: {
4220
+ id: air.id,
4221
+ hash: policyHash
4222
+ }
4223
+ };
4224
+ }
4225
+ function validateGovernanceLock(lock, options = {}) {
4226
+ const errors = [];
4227
+ const warnings = [];
4228
+ const parseResult = GovernanceLockSchema.safeParse(lock);
4229
+ if (!parseResult.success) {
4230
+ return {
4231
+ valid: false,
4232
+ errors: parseResult.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`),
4233
+ warnings: [],
4234
+ expired: false,
4235
+ daysUntilExpiration: 0,
4236
+ signed: false,
4237
+ validSignatureCount: 0,
4238
+ policyHashValid: false
4239
+ };
4240
+ }
4241
+ const parsed = parseResult.data;
4242
+ const now = /* @__PURE__ */ new Date();
4243
+ const expiresAt = new Date(parsed.expires_at);
4244
+ const daysUntilExpiration = Math.ceil((expiresAt.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
4245
+ const expired = expiresAt < now;
4246
+ if (options.checkExpiration !== false && expired) {
4247
+ errors.push(`Lock file expired on ${parsed.expires_at}`);
4248
+ }
4249
+ if (daysUntilExpiration > 0 && daysUntilExpiration <= 7) {
4250
+ warnings.push(`Lock file expires in ${daysUntilExpiration} days`);
4251
+ }
4252
+ const signed = parsed.signatures.length > 0;
4253
+ if (options.requireSignatures && !signed) {
4254
+ errors.push("Lock file requires at least one signature");
4255
+ }
4256
+ let validSignatureCount = 0;
4257
+ for (const sig of parsed.signatures) {
4258
+ if (sig.expires_at) {
4259
+ const sigExpiresAt = new Date(sig.expires_at);
4260
+ if (sigExpiresAt < now) {
4261
+ warnings.push(`Signature from ${sig.signer} has expired`);
4262
+ } else {
4263
+ validSignatureCount++;
4264
+ }
4265
+ } else {
4266
+ validSignatureCount++;
4267
+ }
4268
+ }
4269
+ let policyHashValid = true;
4270
+ if (options.expectedPolicyHash) {
4271
+ if (parsed.policy_hash !== options.expectedPolicyHash) {
4272
+ errors.push(`Policy hash mismatch: expected ${options.expectedPolicyHash}, got ${parsed.policy_hash}`);
4273
+ policyHashValid = false;
4274
+ }
4275
+ }
4276
+ return {
4277
+ valid: errors.length === 0,
4278
+ errors,
4279
+ warnings,
4280
+ expired,
4281
+ daysUntilExpiration,
4282
+ signed,
4283
+ validSignatureCount,
4284
+ policyHashValid
4285
+ };
4286
+ }
4287
+ function parseGovernanceLockYAML(content) {
4288
+ const parsed = yaml2.parse(content);
4289
+ return GovernanceLockSchema.parse(parsed);
4290
+ }
4291
+ function parseGovernanceLockJSON(content) {
4292
+ const parsed = JSON.parse(content);
4293
+ return GovernanceLockSchema.parse(parsed);
4294
+ }
4295
+ function serializeGovernanceLockYAML(lock) {
4296
+ return yaml2.stringify(lock, {
4297
+ indent: 2,
4298
+ lineWidth: 120
4299
+ });
4300
+ }
4301
+ function serializeGovernanceLockJSON(lock, pretty = true) {
4302
+ return pretty ? JSON.stringify(lock, null, 2) : JSON.stringify(lock);
4303
+ }
4304
+ function isGovernanceLockExpired(lock) {
4305
+ return new Date(lock.expires_at) < /* @__PURE__ */ new Date();
4306
+ }
4307
+ function getDaysUntilExpiration(lock) {
4308
+ const now = /* @__PURE__ */ new Date();
4309
+ const expiresAt = new Date(lock.expires_at);
4310
+ return Math.ceil((expiresAt.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
4311
+ }
4312
+ function isVendorAllowedByLock(vendorId, lock) {
4313
+ const { registry: registry2 } = lock.constraints;
4314
+ if (registry2.blocked_vendor_ids.includes(vendorId)) {
4315
+ return false;
4316
+ }
4317
+ if (registry2.allowed_vendor_ids.length > 0) {
4318
+ return registry2.allowed_vendor_ids.includes(vendorId);
4319
+ }
4320
+ return true;
4321
+ }
4322
+ function isModelAllowedByLock(modelId, lock) {
4323
+ const { registry: registry2 } = lock.constraints;
4324
+ for (const pattern of registry2.blocked_model_patterns) {
4325
+ if (matchesPattern3(modelId, pattern)) {
4326
+ return false;
4327
+ }
4328
+ }
4329
+ if (registry2.allowed_model_patterns.length > 0) {
4330
+ return registry2.allowed_model_patterns.some(
4331
+ (pattern) => matchesPattern3(modelId, pattern)
4332
+ );
4333
+ }
4334
+ return true;
4335
+ }
4336
+ function isRegionAllowedByLock(regionCode, lock) {
4337
+ const { registry: registry2 } = lock.constraints;
4338
+ if (registry2.blocked_region_codes.includes(regionCode)) {
4339
+ return false;
4340
+ }
4341
+ if (registry2.allowed_region_codes.length > 0) {
4342
+ return registry2.allowed_region_codes.includes(regionCode);
4343
+ }
4344
+ return true;
4345
+ }
4346
+ function matchesPattern3(value, pattern) {
4347
+ if (pattern === "*") {
4348
+ return true;
4349
+ }
4350
+ if (pattern.endsWith("*")) {
4351
+ return value.startsWith(pattern.slice(0, -1));
4352
+ }
4353
+ if (pattern.startsWith("*")) {
4354
+ return value.endsWith(pattern.slice(1));
4355
+ }
4356
+ return value === pattern;
4357
+ }
4358
+ function createSigningPayload(lock) {
4359
+ const forSigning = {
4360
+ version: lock.version,
4361
+ generated_at: lock.generated_at,
4362
+ policy_hash: lock.policy_hash,
4363
+ expires_at: lock.expires_at,
4364
+ constraints: lock.constraints
4365
+ };
4366
+ return JSON.stringify(forSigning);
4367
+ }
4368
+ function addSignature(lock, signature) {
4369
+ return {
4370
+ ...lock,
4371
+ signatures: [...lock.signatures, signature]
4372
+ };
4373
+ }
4374
+
2269
4375
  // src/utils.ts
2270
4376
  function formatDate(date) {
2271
4377
  return date.toISOString();
@@ -2278,60 +4384,164 @@ function slugify(text) {
2278
4384
  }
2279
4385
  // Annotate the CommonJS export names for ESM import in node:
2280
4386
  0 && (module.exports = {
4387
+ AIRBuildConstraintsSchema,
4388
+ AIRMetadataSchema,
4389
+ AIRModelSchema,
4390
+ AIRPIIFilterConfigSchema,
4391
+ AIRPolicySourceSchema,
4392
+ AIRRegionSchema,
4393
+ AIRRegistryConstraintsSchema,
4394
+ AIRRuntimeConstraintsSchema,
4395
+ AIRSchema,
4396
+ AIRToxicityFilterConfigSchema,
4397
+ AIRVendorSchema,
4398
+ AigrcConfigSchema,
4399
+ AigrcIntegrationsConfigSchema,
4400
+ AigrcRuntimeConfigSchema,
2281
4401
  ApprovalSchema,
4402
+ AssetCardRuntimeSchema,
2282
4403
  AssetCardSchema,
4404
+ CONFIG_ENV_VAR,
4405
+ CONFIG_FILE_NAMES,
4406
+ CapabilitiesManifestSchema,
2283
4407
  ClassificationSchema,
2284
4408
  ConfidenceLevelSchema,
2285
4409
  ConstraintsSchema,
2286
4410
  ControlStatusSchema,
2287
4411
  DetectionStrategySchema,
2288
4412
  FrameworkCategorySchema,
4413
+ GoldenThreadSchema,
4414
+ GovernanceLockBuildConstraintsSchema,
4415
+ GovernanceLockConstraintsSchema,
4416
+ GovernanceLockPolicySourceSchema,
4417
+ GovernanceLockRegistryConstraintsSchema,
4418
+ GovernanceLockRuntimeConstraintsSchema,
4419
+ GovernanceLockSchema,
4420
+ GovernanceLockSignatureSchema,
2289
4421
  GovernanceSchema,
4422
+ GovernanceTokenCapabilityClaimsSchema,
4423
+ GovernanceTokenControlClaimsSchema,
4424
+ GovernanceTokenGovernanceClaimsSchema,
4425
+ GovernanceTokenIdentityClaimsSchema,
4426
+ GovernanceTokenLineageClaimsSchema,
4427
+ GovernanceTokenPayloadSchema,
2290
4428
  IntentSchema,
2291
4429
  JurisdictionClassificationSchema,
4430
+ KillSwitchCommandSchema,
4431
+ KillSwitchCommandTypeSchema,
4432
+ LineageSchema,
4433
+ MAX_INHERITANCE_DEPTH,
2292
4434
  MODEL_EXTENSIONS,
4435
+ OperatingModeSchema,
2293
4436
  OwnerSchema,
4437
+ PolicyCapabilitiesSchema,
4438
+ PolicyFileSchema,
4439
+ PolicyResolutionError,
4440
+ PolicyRuleEffectSchema,
4441
+ PolicyRuleSchema,
2294
4442
  RiskFactorsSchema,
4443
+ RiskLevelSchema,
4444
+ RuntimeIdentitySchema,
2295
4445
  TechnicalSchema,
2296
4446
  TrustworthinessCharacteristicSchema,
2297
4447
  TrustworthinessSchema,
2298
4448
  addJurisdiction,
4449
+ addSignature,
2299
4450
  analyzeImports,
2300
4451
  applyImplicationChains,
2301
4452
  classifyRisk,
2302
4453
  clearRegistry,
4454
+ compareRiskLevels,
4455
+ computeCanonicalString,
4456
+ computeGoldenThreadHash,
4457
+ computeGoldenThreadHashSync,
4458
+ computeHash,
2303
4459
  createAssetCard,
4460
+ createDefaultConfig,
4461
+ createEmptyAIR,
4462
+ createGoldenThread,
4463
+ createGoldenThreadSync,
4464
+ createGovernanceLock,
2304
4465
  createImplication,
4466
+ createPolicyRepository,
4467
+ createPolicySelector,
4468
+ createSigningPayload,
2305
4469
  detectAnnotations,
4470
+ discoverAssets,
4471
+ discoverConfig,
4472
+ discoverConfigSync,
4473
+ discoverPolicies,
4474
+ evaluatePolicy,
4475
+ extractGoldenThreadComponents,
2306
4476
  formatDate,
2307
4477
  generateAssetId,
2308
4478
  getAllPatterns,
4479
+ getCurrentEnvironment,
4480
+ getDaysUntilExpiration,
4481
+ getEnvironmentConfig,
4482
+ getMaxRiskLevel,
4483
+ getMinRiskLevel,
2309
4484
  getPattern,
2310
4485
  getPatternsByCategory,
2311
4486
  getPatternsByLanguage,
4487
+ getRiskLevelOrdinal,
4488
+ getRiskLevelsAtLeast,
4489
+ getRiskLevelsAtMost,
2312
4490
  inferRiskFactors,
2313
4491
  initializePatterns,
4492
+ isDomainAllowed,
4493
+ isGovernanceLockExpired,
4494
+ isModelAllowed,
4495
+ isModelAllowedByLock,
2314
4496
  isModelFile,
4497
+ isRegionAllowed,
4498
+ isRegionAllowedByLock,
2315
4499
  isRegistryInitialized,
4500
+ isRiskLevelAtLeast,
4501
+ isRiskLevelAtMost,
4502
+ isToolAllowed,
4503
+ isValidRiskLevel,
4504
+ isVendorAllowed,
4505
+ isVendorAllowedByLock,
2316
4506
  javascriptPatterns,
2317
4507
  linkAssetToTicket,
4508
+ loadAsset,
2318
4509
  loadAssetCard,
4510
+ loadAssetFromPath,
4511
+ loadPolicy,
4512
+ mapToEuAiActCategory,
2319
4513
  matchPatterns,
4514
+ mergePolicies,
2320
4515
  modelFilePatterns,
2321
4516
  parseDate,
4517
+ parseGovernanceLockJSON,
4518
+ parseGovernanceLockYAML,
4519
+ parseRiskLevel,
4520
+ parseSignature,
2322
4521
  pythonPatterns,
2323
4522
  registerPattern,
2324
4523
  resetPatterns,
4524
+ resolvePolicy,
2325
4525
  riskIndicatorPatterns,
2326
4526
  saveAssetCard,
2327
4527
  scan,
2328
4528
  scanFileExtension,
2329
4529
  scanSync,
4530
+ selectPolicy,
4531
+ serializeGovernanceLockJSON,
4532
+ serializeGovernanceLockYAML,
4533
+ signGoldenThread,
2330
4534
  slugify,
2331
4535
  suggestAssetCard,
2332
4536
  updateJurisdictionCompliance,
4537
+ validateAIR,
2333
4538
  validateAssetCard,
2334
4539
  validateGoldenThread,
2335
- validateRiskFactors
4540
+ validateGovernanceLock,
4541
+ validateRiskFactors,
4542
+ verifyGoldenThreadHash,
4543
+ verifyGoldenThreadHashSync,
4544
+ verifyGoldenThreadSignature,
4545
+ verifyGoldenThreadSignatureSync
2336
4546
  });
2337
4547
  //# sourceMappingURL=index.js.map