@opengeni/core 6.7.0 → 6.7.1-canary.41759707569001

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.
@@ -21,6 +21,10 @@ export declare function secretRedactionReferenceLabel(reference: Pick<SecretRefe
21
21
  * so a run with a one-character or all-blank "secret" can never rewrite
22
22
  * everything. Also null for a value holding marker-shaped text, which the
23
23
  * scrub could never find.
24
+ *
25
+ * A person asked for this value to be removed from stored history, so a
26
+ * weak value (a word, a host) is removed wherever it appears too, not only
27
+ * in credential positions as live masking does.
24
28
  */
25
29
  export declare function secretRedactionMatcherForValue(value: string, label: string): SecretRedactionMatcher | null;
26
30
  export declare function maskInPatternWindows(text: string, mask: (window: string) => string, windowChars?: number): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The save-time nudge for plain fields (docs/secrets.md, Field kinds). A
3
+ * value that looks like a secret in a field that would be saved as `text`
4
+ * is saved as `concealed` when nobody chose the kind (a new field whose
5
+ * default is text), and kept as text with a note when `text` was asked for,
6
+ * the field already is text, or it is a standard text field of the item's
7
+ * type (a login's `username`). Only saves that report notes (the agent's
8
+ * `secret_save`) are nudged: without `notes` the kind is unchanged, so a
9
+ * kind never changes silently. Nothing here refuses a save.
10
+ */
11
+ import { type SecretSaveFieldNote, type VaultFieldKind } from "@opengeni/contracts";
12
+ export declare function plainFieldKind(input: {
13
+ name: string;
14
+ value: string;
15
+ kind: VaultFieldKind;
16
+ chosen: boolean;
17
+ }, notes: SecretSaveFieldNote[] | undefined): VaultFieldKind;
@@ -1,4 +1,4 @@
1
- import { type VaultFieldInput, type VaultFieldKind, type VaultItemType, type VaultProviderOperations } from "@opengeni/contracts";
1
+ import { type SecretSaveFieldNote, type VaultFieldInput, type VaultFieldKind, type VaultItemType, type VaultProviderOperations } from "@opengeni/contracts";
2
2
  import { VaultError, type Database, type VaultDbContext, type VaultFieldRow, type VaultRow } from "@opengeni/db";
3
3
  import { type ProviderCallBudget, type VaultProvider, type VaultProviderRegistry } from "@opengeni/vaults";
4
4
  import { type ProviderVaultSyncResult } from "./provider-sync.js";
@@ -96,6 +96,8 @@ export declare function writeProviderVaultItemOutcome(deps: ProviderWriteDeps, i
96
96
  change: ProviderItemChange;
97
97
  /** Receives the names of fields whose values were generated. */
98
98
  generated?: string[];
99
+ /** Receives a note for each plain field whose value looks like a secret. */
100
+ fieldNotes?: SecretSaveFieldNote[];
99
101
  }): Promise<ProviderWriteOutcome>;
100
102
  /** Thrown when a confirmed provider write is not listed yet: it must not be saved again. */
101
103
  export declare function savedNotListedError(vault: VaultRow, itemName: string, outcome: Extract<ProviderWriteOutcome, {
package/dist/index.js CHANGED
@@ -7537,6 +7537,7 @@ import {
7537
7537
  isDirectModelId,
7538
7538
  MESSAGE_TIME_ZONE_METADATA_KEY,
7539
7539
  messageSentByPerson,
7540
+ ModelPolicyRefusedError,
7540
7541
  ModelUnavailableError,
7541
7542
  normalizeMessageTimeZone
7542
7543
  } from "@opengeni/contracts";
@@ -15952,8 +15953,10 @@ async function assertWorkspaceModelPolicyAllows(db, settings, workspaceId, model
15952
15953
  chargesCredits: policyChargesCreditsForModel(settings, canonicalModel)
15953
15954
  });
15954
15955
  if (!verdict.allowed) {
15956
+ const message = verdict.reason === "credits" ? `model "${canonicalModel}" uses credits, which are turned off in this workspace. Choose a model paid by a subscription or API key, or ask a workspace admin to turn credits back on` : verdict.reason === "provider" ? `model "${canonicalModel}" is not allowed by this workspace's model policy: provider "${providerId}" is not in the allowed providers` : `model "${canonicalModel}" is not allowed by this workspace's model policy`;
15955
15957
  throw new HTTPException24(422, {
15956
- message: verdict.reason === "credits" ? `model "${canonicalModel}" uses credits, which are turned off in this workspace. Choose a model paid by a subscription or API key, or ask a workspace admin to turn credits back on` : verdict.reason === "provider" ? `model "${canonicalModel}" is not allowed by this workspace's model policy: provider "${providerId}" is not in the allowed providers` : `model "${canonicalModel}" is not allowed by this workspace's model policy`
15958
+ message,
15959
+ cause: new ModelPolicyRefusedError(canonicalModel, verdict.reason, message)
15957
15960
  });
15958
15961
  }
15959
15962
  }
@@ -17125,7 +17128,10 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
17125
17128
  ...claudeProviderAccountAuthoritySnapshot ? { claudeAuthoritySnapshot: claudeProviderAccountAuthoritySnapshot } : {}
17126
17129
  });
17127
17130
  if (!admissibleWorkspaceModel(selections, model)) {
17128
- throw new HTTPException24(422, { message: `model is not selectable: ${model}` });
17131
+ throw new HTTPException24(422, {
17132
+ message: `model is not selectable: ${model}`,
17133
+ cause: new ModelUnavailableError(model)
17134
+ });
17129
17135
  }
17130
17136
  }
17131
17137
  });
@@ -19693,7 +19699,7 @@ function secretRedactionMatcherForValue(value, label) {
19693
19699
  if (containsSecretRedactionMarker(value)) return null;
19694
19700
  if (secretValueForms(value, { minChars: SECRET_VALUE_MASK_MIN_CHARS }).length === 0) return null;
19695
19701
  const marker = secretRedactionMarker(label);
19696
- const masks = compileSecretValueMasks([{ value, label: marker }]);
19702
+ const masks = compileSecretValueMasks([{ value, label: marker }], { weakValues: "anywhere" });
19697
19703
  return { marker, redact: (text5) => maskSecretValuesInText(text5, masks) };
19698
19704
  }
19699
19705
  var GITHUB_TOKEN = /^(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{30,255})$/u;
@@ -23774,6 +23780,32 @@ import {
23774
23780
  readProviderItemInventory as readProviderItemInventory2
23775
23781
  } from "@opengeni/vaults";
23776
23782
 
23783
+ // src/domain/vaults/plain-field-hints.ts
23784
+ import {
23785
+ plainFieldSecretHint
23786
+ } from "@opengeni/contracts";
23787
+ function plainFieldKind(input, notes) {
23788
+ if (notes === void 0 || input.kind !== "text") return input.kind;
23789
+ const hint = plainFieldSecretHint(input.name, input.value);
23790
+ if (!hint) return input.kind;
23791
+ if (input.chosen) {
23792
+ notes?.push({
23793
+ field: input.name,
23794
+ kind: "text",
23795
+ reason: hint.reason,
23796
+ message: `${hint.message} Kept as text; save it with kind "concealed" if it is a secret.`
23797
+ });
23798
+ return "text";
23799
+ }
23800
+ notes?.push({
23801
+ field: input.name,
23802
+ kind: "concealed",
23803
+ reason: hint.reason,
23804
+ message: `${hint.message} Saved as concealed; save it with kind "text" if it is not a secret.`
23805
+ });
23806
+ return "concealed";
23807
+ }
23808
+
23777
23809
  // src/domain/vaults/typed-fields.ts
23778
23810
  import {
23779
23811
  VAULT_ITEM_TYPE_FIELDS,
@@ -24020,7 +24052,7 @@ function fileContent(input, current) {
24020
24052
  const name = input.fileName ?? current?.fileName ?? input.name;
24021
24053
  return { name, bytes };
24022
24054
  }
24023
- async function providerFieldValues(planned, resolveReference, generated) {
24055
+ async function providerFieldValues(type, planned, resolveReference, generated, fieldNotes) {
24024
24056
  const writes = [];
24025
24057
  for (const { input, base, kind, current } of planned) {
24026
24058
  if (input.remove) {
@@ -24048,7 +24080,16 @@ async function providerFieldValues(planned, resolveReference, generated) {
24048
24080
  }
24049
24081
  value = value.trim();
24050
24082
  }
24051
- writes.push({ ...base, value });
24083
+ const saved = plainFieldKind(
24084
+ {
24085
+ name: input.name,
24086
+ value,
24087
+ kind,
24088
+ chosen: input.kind !== void 0 || current !== void 0 || standardFieldKind(type, input.name) === "text"
24089
+ },
24090
+ fieldNotes
24091
+ );
24092
+ writes.push({ ...base, kind: saved, value });
24052
24093
  }
24053
24094
  return writes;
24054
24095
  }
@@ -24173,7 +24214,13 @@ async function writeProviderVaultItemOutcome(deps, input) {
24173
24214
  ),
24174
24215
  existing?.fields ?? []
24175
24216
  );
24176
- const fields = await providerFieldValues(planned, deps.resolveReference, input.generated ?? []);
24217
+ const fields = await providerFieldValues(
24218
+ type,
24219
+ planned,
24220
+ deps.resolveReference,
24221
+ input.generated ?? [],
24222
+ input.fieldNotes
24223
+ );
24177
24224
  const name = change.name ?? existing?.name ?? "";
24178
24225
  const category = change.category !== void 0 ? change.category : existing?.category ?? null;
24179
24226
  let written;
@@ -24610,7 +24657,7 @@ function defaultFieldKind(type, name) {
24610
24657
  }
24611
24658
  function createVaultService(deps) {
24612
24659
  const clock = deps.clock ?? systemSecretClock;
24613
- async function fieldWrite(input, existing, type, resolveReference, generated) {
24660
+ async function fieldWrite(input, existing, type, resolveReference, generated, fieldNotes) {
24614
24661
  const current = existing?.fields.find(
24615
24662
  (field) => input.fieldId !== void 0 && field.id === input.fieldId || secretNameKey5(field.name) === secretNameKey5(input.name)
24616
24663
  );
@@ -24641,6 +24688,15 @@ function createVaultService(deps) {
24641
24688
  plaintext = input.value ?? "";
24642
24689
  size = utf8Size(plaintext);
24643
24690
  }
24691
+ kind = plainFieldKind(
24692
+ {
24693
+ name: input.name,
24694
+ value: plaintext,
24695
+ kind,
24696
+ chosen: input.kind !== void 0 || current !== void 0 || standardFieldKind(type, input.name) === "text"
24697
+ },
24698
+ fieldNotes
24699
+ );
24644
24700
  if (kind === "totp") {
24645
24701
  if (!isValidTotpInput3(plaintext)) {
24646
24702
  throw new VaultError4(
@@ -24706,7 +24762,7 @@ function createVaultService(deps) {
24706
24762
  if (value.material.type === "bytes") return Buffer.from(value.material.value).toString("utf8");
24707
24763
  return totpCodeSync(value.material.params, clock.now());
24708
24764
  }
24709
- async function itemWrite(req, existing, resolveReference, createdBy, generated = []) {
24765
+ async function itemWrite(req, existing, resolveReference, createdBy, generated = [], fieldNotes) {
24710
24766
  const write = { createdByKind: createdBy };
24711
24767
  if (req.name !== void 0) write.name = req.name;
24712
24768
  if (req.type !== void 0) write.type = req.type;
@@ -24719,7 +24775,9 @@ function createVaultService(deps) {
24719
24775
  const fields = await prepareTypedFields(type, req.fields, resolveReference, generated);
24720
24776
  write.fields = [];
24721
24777
  for (const field of fields) {
24722
- write.fields.push(await fieldWrite(field, existing, type, resolveReference, generated));
24778
+ write.fields.push(
24779
+ await fieldWrite(field, existing, type, resolveReference, generated, fieldNotes)
24780
+ );
24723
24781
  }
24724
24782
  }
24725
24783
  return write;
@@ -25498,6 +25556,8 @@ function createVaultService(deps) {
25498
25556
  fields.unshift({ name: "username", kind: "text", value: input.username });
25499
25557
  }
25500
25558
  const generated = [];
25559
+ const fieldNotes = [];
25560
+ const notes = () => fieldNotes.length > 0 ? { fieldNotes } : {};
25501
25561
  if (vault.source !== "opengeni") {
25502
25562
  const itemId = await writeProviderVaultItem(
25503
25563
  {
@@ -25523,14 +25583,16 @@ function createVaultService(deps) {
25523
25583
  ...input.websites !== void 0 ? { websites: input.websites } : {},
25524
25584
  fields
25525
25585
  },
25526
- generated
25586
+ generated,
25587
+ fieldNotes
25527
25588
  }
25528
25589
  );
25529
25590
  const saved = await getVaultItem2(deps.db, context, { itemId });
25530
25591
  return {
25531
25592
  item: toVaultItemSummary(saved, key()),
25532
25593
  references: vaultItemReferences(saved),
25533
- generatedFields: generated
25594
+ generatedFields: generated,
25595
+ ...notes()
25534
25596
  };
25535
25597
  }
25536
25598
  const write = await itemWrite(
@@ -25543,7 +25605,8 @@ function createVaultService(deps) {
25543
25605
  fullExisting,
25544
25606
  (raw) => resolveTextReference(principal, raw, "secret_save"),
25545
25607
  "agent",
25546
- generated
25608
+ generated,
25609
+ fieldNotes
25547
25610
  );
25548
25611
  const row = await upsertVaultItem(
25549
25612
  deps.db,
@@ -25551,7 +25614,12 @@ function createVaultService(deps) {
25551
25614
  fullExisting ? { ...write, itemId: fullExisting.id } : { ...write, vaultId: vault.id, mode: "create" }
25552
25615
  );
25553
25616
  const summary = toVaultItemSummary(row, key());
25554
- return { item: summary, references: vaultItemReferences(row), generatedFields: generated };
25617
+ return {
25618
+ item: summary,
25619
+ references: vaultItemReferences(row),
25620
+ generatedFields: generated,
25621
+ ...notes()
25622
+ };
25555
25623
  },
25556
25624
  async captureForAgent(principal, input) {
25557
25625
  if (principal.kind !== "attempt") {