@homeflare/alchemy 0.51.0 → 0.53.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.
Files changed (73) hide show
  1. package/dist/grafana/folder-permission.d.ts +76 -0
  2. package/dist/grafana/folder-permission.d.ts.map +1 -0
  3. package/dist/grafana/index.d.ts +3 -1
  4. package/dist/grafana/index.d.ts.map +1 -1
  5. package/dist/grafana/index.js +133 -46
  6. package/dist/grafana/index.js.map +7 -5
  7. package/dist/grafana/providers.d.ts +1 -1
  8. package/dist/grafana/providers.d.ts.map +1 -1
  9. package/dist/grafana/provisioned.d.ts +1 -1
  10. package/dist/grafana/provisioned.d.ts.map +1 -1
  11. package/dist/grafana/team.d.ts +64 -0
  12. package/dist/grafana/team.d.ts.map +1 -0
  13. package/dist/linux/container-env-quote.d.ts +39 -0
  14. package/dist/linux/container-env-quote.d.ts.map +1 -0
  15. package/dist/linux/container-form.d.ts +14 -13
  16. package/dist/linux/container-form.d.ts.map +1 -1
  17. package/dist/linux/container-paths.d.ts +17 -0
  18. package/dist/linux/container-paths.d.ts.map +1 -0
  19. package/dist/linux/index.js +41 -8
  20. package/dist/linux/index.js.map +6 -4
  21. package/dist/litellm/fake-marketplace-litellm.d.ts +33 -0
  22. package/dist/litellm/fake-marketplace-litellm.d.ts.map +1 -0
  23. package/dist/litellm/index.d.ts +1 -0
  24. package/dist/litellm/index.d.ts.map +1 -1
  25. package/dist/litellm/index.js +530 -329
  26. package/dist/litellm/index.js.map +7 -4
  27. package/dist/litellm/marketplace-form.d.ts +21 -0
  28. package/dist/litellm/marketplace-form.d.ts.map +1 -0
  29. package/dist/litellm/marketplace-operations.d.ts +27 -0
  30. package/dist/litellm/marketplace-operations.d.ts.map +1 -0
  31. package/dist/litellm/marketplace-plugin.d.ts +57 -0
  32. package/dist/litellm/marketplace-plugin.d.ts.map +1 -0
  33. package/dist/litellm/marketplace-types.d.ts +55 -0
  34. package/dist/litellm/marketplace-types.d.ts.map +1 -0
  35. package/dist/litellm/providers.d.ts +1 -1
  36. package/dist/litellm/providers.d.ts.map +1 -1
  37. package/dist/unifi/index.js.map +2 -2
  38. package/dist/unifi/network.d.ts +2 -1
  39. package/dist/unifi/network.d.ts.map +1 -1
  40. package/docs/litellm-marketplace.md +59 -0
  41. package/docs/litellm.md +1 -0
  42. package/docs/unifi.md +11 -10
  43. package/package.json +1 -1
  44. package/src/grafana/folder-permission.test.ts +107 -0
  45. package/src/grafana/folder-permission.ts +128 -0
  46. package/src/grafana/index.ts +10 -1
  47. package/src/grafana/providers.ts +4 -0
  48. package/src/grafana/provisioned.ts +1 -1
  49. package/src/grafana/team.test.ts +108 -0
  50. package/src/grafana/team.ts +105 -0
  51. package/src/linux/container-env-chain.test.ts +135 -0
  52. package/src/linux/container-env-live.test.ts +115 -0
  53. package/src/linux/container-env-oracle.ts +109 -0
  54. package/src/linux/container-env-quadlet-oracle.ts +174 -0
  55. package/src/linux/container-env-quote.test.ts +131 -0
  56. package/src/linux/container-env-quote.ts +126 -0
  57. package/src/linux/container-fixture.test.ts +3 -1
  58. package/src/linux/container-form.ts +32 -28
  59. package/src/linux/container-paths.ts +21 -0
  60. package/src/litellm/fake-marketplace-litellm.test.ts +51 -0
  61. package/src/litellm/fake-marketplace-litellm.ts +134 -0
  62. package/src/litellm/index.ts +8 -0
  63. package/src/litellm/marketplace-form.ts +160 -0
  64. package/src/litellm/marketplace-operations.ts +76 -0
  65. package/src/litellm/marketplace-plugin-replace.test.ts +68 -0
  66. package/src/litellm/marketplace-plugin.test.ts +181 -0
  67. package/src/litellm/marketplace-plugin.ts +156 -0
  68. package/src/litellm/marketplace-types.ts +53 -0
  69. package/src/litellm/providers.ts +2 -0
  70. package/src/litellm/registry-exports.test.ts +6 -0
  71. package/src/unifi/network-scope.test.ts +21 -0
  72. package/src/unifi/network.ts +2 -1
  73. package/src/unifi/write-op-reference.test.ts +3 -2
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/grafana/alert-rule-group.ts", "../src/grafana/alert-rule-group-drop-warning.ts", "../src/grafana/alert-rule-group-model.ts", "../src/grafana/alerting-provenance.ts", "../src/grafana/provisioned.ts", "../src/grafana/resource.ts", "../src/grafana/subset-match.ts", "../src/grafana/notification-policy.ts", "../src/grafana/notification-policy-model.ts", "../src/grafana/notification-policy-drop-warning.ts", "../src/grafana/datasource.ts", "../src/grafana/secret-refs.ts", "../src/grafana/dashboard.ts", "../src/grafana/dashboard-model.ts", "../src/grafana/folder.ts", "../src/grafana/contact-point.ts", "../src/grafana/message-template.ts", "../src/grafana/mute-timing.ts", "../src/grafana/credentials.ts", "../src/grafana/providers.ts"],
3
+ "sources": ["../src/grafana/alert-rule-group.ts", "../src/grafana/alert-rule-group-drop-warning.ts", "../src/grafana/alert-rule-group-model.ts", "../src/grafana/alerting-provenance.ts", "../src/grafana/provisioned.ts", "../src/grafana/resource.ts", "../src/grafana/subset-match.ts", "../src/grafana/notification-policy.ts", "../src/grafana/notification-policy-model.ts", "../src/grafana/notification-policy-drop-warning.ts", "../src/grafana/datasource.ts", "../src/grafana/secret-refs.ts", "../src/grafana/dashboard.ts", "../src/grafana/dashboard-model.ts", "../src/grafana/folder.ts", "../src/grafana/team.ts", "../src/grafana/folder-permission.ts", "../src/grafana/contact-point.ts", "../src/grafana/message-template.ts", "../src/grafana/mute-timing.ts", "../src/grafana/credentials.ts", "../src/grafana/providers.ts"],
4
4
  "sourcesContent": [
5
5
  "/**\n * `Grafana.AlertRuleGroup` — one Grafana alert rule GROUP, keyed by `(folderUid, group)`.\n *\n * ★ GROUP, NOT PER-RULE — THE UNIT CHOICE, JUSTIFIED. MEASURED against the SDK's generated\n * operations: `PUT /v1/provisioning/folder/{FolderUID}/rule-groups/{Group}`\n * (`routePutAlertRuleGroup`) takes the evaluation `interval` AND the full ordered `rules[]`\n * TOGETHER, replacing the whole group in one call (`RoutePutAlertRuleGroupRequest.rules:\n * Array<ProvisionedAlertRuleInput>`) — the individual `routePostAlertRule`/`routePutAlertRule`\n * operations have no `interval` field at all and cannot reorder rules within a group. Declaring\n * rules one at a time (`Grafana.AlertRule`) would leave a group's evaluation interval and rule\n * order — both real, load-bearing Grafana state — either undeclarable or racy across N\n * independent resources with no shared source of truth for them. Grafana's own docs describe\n * `X-Disable-Provenance` on the rule-group PUT as setting \"the provenance for the rule group AND\n * ALL ITS ALERT RULES\" — further evidence the group, not the rule, is Grafana's own natural unit\n * of ownership here. Mirrors Terraform's own `grafana_rule_group` resource, which takes the\n * identical shape (a list of rules under one folder/name/interval).\n *\n * ★ `uid` IS REQUIRED ON EVERY DECLARED RULE — same doctrine as every other resource in this\n * family (`AlertRuleInput` in `alert-rule-group-model.ts`). `ProvisionedAlertRuleInput.uid` is\n * optional on the wire (Grafana assigns one if omitted), but locating a specific rule this\n * resource didn't just create would then mean matching by title — the same ambiguity\n * `resource.ts`'s header and netbox's `soleMatch` exist to catch everywhere else in this family.\n *\n * ⛔ RULE ORDER IS SIGNIFICANT — NEVER REORDERED. `subset-match.ts`'s array comparison is already\n * position-significant (length, then element-wise) — this resource relies on that as-is; nothing\n * here re-sorts `rules` before comparing. Declaring rules in a different order than what is live\n * is a genuine content change (Grafana evaluates and displays a group's rules in array order),\n * not a cosmetic one.\n *\n * ⛔ A FOREIGN-PROVENANCE GROUP REFUSES EVERY UPDATE AND DESTROY — `alerting-provenance.ts`. Unlike\n * `ContactPoint`/`MessageTemplate`, `AlertRuleGroup` (the type `routeGetAlertRuleGroup` returns)\n * carries NO top-level `provenance` field — MEASURED: `folderUid?`/`interval?`/`rules?`/`title?`\n * only. Each RULE inside `rules[]` has its own (`ProvisionedAlertRule.provenance`), and Grafana's\n * docs say a new rule's provenance \"must match the provenance value configured for its rule\n * group\" — so this resource checks every live rule and refuses if ANY carries a foreign\n * provenance, naming the first one found. An empty live group (no rules yet) has nothing to check\n * and is never foreign. `create` is never at risk: it only runs when `fetchLive` already found\n * nothing.\n *\n * ⛔ A DECLARED GROUP WHOSE FOLDER DOES NOT EXIST REFUSES — IT IS NEVER AUTO-CREATED. This resource\n * makes no \"does the folder exist\" call of its own and does not depend on or invoke\n * `Grafana.Folder`'s create path. MEASURED: `RoutePutAlertRuleGroupError` is\n * `BadRequest | Forbidden | GrafanaOpError` — no `NotFound` case at all — so a nonexistent\n * `folderUid` fails the PUT as a typed `BadRequest`, left uncaught and propagated (the house rule\n * against folding a non-not-found error into absent), which fails the whole `reconcile` and stops\n * the deploy. Declare a `Grafana.Folder` for it first — the two resources sharing one `folderUid`\n * string is the dependency; auto-creating a folder from inside this resource would blur ownership\n * the same way `provisioned.ts`'s \"one owner per resource\" principle already guards against\n * elsewhere in this family. ⚠️ NOT RE-MEASURED against a live instance in this PR — inferred from\n * the declared error union, the same evidentiary bar `folder.ts`'s own `version` note uses.\n *\n * ⛔ DELETE DEFAULTS TO `retain` — DELETING A GROUP DELETES EVERY RULE IN IT IN ONE CALL\n * (`routeDeleteAlertRuleGroup`, whole-group DELETE). The same multi-object-cascade class\n * `Grafana.Folder`/`openbao/mount.ts` already guard with `defaultRemovalPolicy: 'retain'` — a\n * stack that wants the cascade opts in with `.pipe(RemovalPolicy.destroy())`; `destroy` below\n * still implements the real DELETE in full either way (S11).\n *\n * ⚠️ `orgID` DEFAULTS TO `1` ON EVERY WRITTEN RULE — see `alert-rule-group-model.ts`'s own note;\n * not measured against a multi-org instance, since none exists in this house yet.\n *\n * ⚠️ `X-Disable-Provenance` IS NEVER SET — same reasoning as `contact-point.ts`'s file header.\n *\n * ⚠️ A WHOLE-GROUP WRITE SILENTLY DROPS ANY LIVE RULE THE DECLARATION DOESN'T MENTION — flagged by\n * an adversarial review of this PR. Unlike every other resource in this family, this one does\n * not compare one object's fields; `update`/`diff` REPLACE an entire collection, so a live rule\n * with no counterpart in `props.rules` (e.g. one a human just added in the Grafana UI, ordinary\n * writable provenance — nothing for the refusal above to catch) is removed with no error and no\n * distinct `Diff` action to report it under. This is accepted by design — the group is still the\n * unit — but never SILENT: `alert-rule-group-drop-warning.ts`'s `warnOnDroppedRules` logs every\n * dropped rule by title and uid, called from both the custom `diff` below (so `bun run plan`\n * shows it before anything is written) and from `update` itself (so it is visible wherever\n * `reconcile` runs directly too).\n */\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Effect from 'effect/Effect';\nimport { warnOnDroppedRules } from './alert-rule-group-drop-warning.ts';\nimport { type AlertRuleInput, normalizeRule, toWireRule } from './alert-rule-group-model.ts';\nimport {\n type GrafanaProvisionedObjectError,\n isForeignProvenance,\n refuseIfForeignProvenance,\n} from './alerting-provenance.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\nimport { declaredContentMatches } from './subset-match.ts';\n\nexport type { AlertRuleInput };\n\nexport interface AlertRuleGroupProps {\n folderUid: string;\n group: string;\n /** Evaluation interval, in seconds. */\n interval: number;\n /** Order is significant — see the file header. */\n rules: ReadonlyArray<AlertRuleInput>;\n}\n\nexport interface AlertRuleGroupAttributes {\n folderUid: string;\n group: string;\n interval: number;\n rules: ReadonlyArray<Record<string, unknown>>;\n}\n\nexport interface GrafanaAlertRuleGroup extends Resource<\n 'Grafana.AlertRuleGroup',\n AlertRuleGroupProps,\n AlertRuleGroupAttributes,\n never\n> {}\n\nexport const GrafanaAlertRuleGroup = Resource<GrafanaAlertRuleGroup>('Grafana.AlertRuleGroup', {\n defaultRemovalPolicy: 'retain',\n});\n\n/** The first live rule whose provenance this family may not write to, or `undefined` when every\n * rule (including none at all) is writable. */\nconst findForeignRule = (\n rules: ReadonlyArray<grafana.ProvisionedAlertRule> | undefined,\n): grafana.ProvisionedAlertRule | undefined =>\n (rules ?? []).find((rule) => isForeignProvenance(rule.provenance));\n\nconst body = (props: AlertRuleGroupProps) => ({\n folderUid: props.folderUid,\n interval: props.interval,\n rules: props.rules.map((rule) => toWireRule(rule, props.folderUid, props.group)),\n title: props.group,\n});\n\nconst refuseForForeignRule = (props: AlertRuleGroupProps, foreign: grafana.ProvisionedAlertRule) =>\n refuseIfForeignProvenance(\n 'Grafana.AlertRuleGroup',\n `${props.folderUid}/${props.group}`,\n foreign.provenance,\n );\n\nconst declaredUids = (props: AlertRuleGroupProps): ReadonlySet<string> =>\n new Set(props.rules.map((rule) => rule.uid));\n\nexport const spec: GrafanaSpec<\n AlertRuleGroupProps,\n grafana.AlertRuleGroup,\n AlertRuleGroupAttributes,\n | grafana.RouteGetAlertRuleGroupError\n | grafana.RoutePutAlertRuleGroupError\n | grafana.RouteDeleteAlertRuleGroupError\n | GrafanaProvisionedObjectError\n> = {\n attributes: (live, props) => ({\n folderUid: live.folderUid ?? props.folderUid,\n group: props.group,\n interval: live.interval ?? 0,\n rules: (live.rules ?? []).map((rule) =>\n normalizeRule(rule as unknown as Record<string, unknown>, props.folderUid, props.group),\n ),\n }),\n create: (props) =>\n grafana.routePutAlertRuleGroup({\n FolderUID: props.folderUid,\n Group: props.group,\n ...body(props),\n }),\n destroy: (props, live) =>\n Effect.gen(function* () {\n const foreign = findForeignRule(live.rules);\n if (foreign !== undefined) return yield* refuseForForeignRule(props, foreign);\n yield* grafana.routeDeleteAlertRuleGroup({ FolderUID: props.folderUid, Group: props.group });\n }),\n fetchLive: (props) =>\n grafana\n .routeGetAlertRuleGroup({ FolderUID: props.folderUid, Group: props.group })\n .pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n matches: (attributes, props) =>\n attributes.interval === props.interval &&\n declaredContentMatches(\n props.rules.map((rule) =>\n normalizeRule(rule as unknown as Record<string, unknown>, props.folderUid, props.group),\n ),\n attributes.rules,\n ),\n update: (props, live) =>\n Effect.gen(function* () {\n const foreign = findForeignRule(live.rules);\n if (foreign !== undefined) return yield* refuseForForeignRule(props, foreign);\n yield* warnOnDroppedRules(props.folderUid, props.group, declaredUids(props), live.rules);\n yield* grafana.routePutAlertRuleGroup({\n FolderUID: props.folderUid,\n Group: props.group,\n ...body(props),\n });\n }),\n};\n\n/**\n * ⚠️ A LOCAL REIMPLEMENTATION OF `resource.ts`'s GENERIC `diff`, NOT A WRAP OF IT — deliberately.\n * The generic `grafanaOperations(spec).diff` fetches live and maps it to `Attributes` entirely\n * inside itself, with no seam to run the drop warning against the rules it read; wrapping it\n * would mean a SECOND live fetch just to see what it saw. This resource's `diff` is the ONLY one\n * in the family that needs a resource-specific side effect mid-comparison, so it re-reads\n * `resource.ts`'s own logic here rather than changing the shared engine every other resource\n * also uses. Keep this in sync with `resource.ts`'s `grafanaOperations.diff` if that ever\n * changes shape.\n */\nconst diff = ({\n news,\n output,\n}: {\n news: Input<AlertRuleGroupProps>;\n output: AlertRuleGroupAttributes | undefined;\n}) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* spec.fetchLive(news);\n if (live === undefined) return { action: 'update' } as const;\n yield* warnOnDroppedRules(news.folderUid, news.group, declaredUids(news), live.rules);\n const mapped = spec.attributes(live, news);\n return mapped !== undefined && spec.matches(mapped, news)\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n });\n\nexport const handlers = { ...grafanaHandlers(spec), diff };\n\nexport const GrafanaAlertRuleGroupProvider = () =>\n Provider.effect(\n GrafanaAlertRuleGroup,\n Effect.succeed(GrafanaAlertRuleGroup.Provider.of(handlers)),\n );\n",
6
6
  "/**\n * The warning `Grafana.AlertRuleGroup` logs when a whole-group PUT would silently drop a live rule\n * the declaration never mentions — flagged by an adversarial review of this PR: a human adding a\n * rule in the Grafana UI minutes before a deploy (ordinary, writable provenance — nothing foreign\n * to refuse on) would otherwise be removed with no visible reason, `diff` only ever saying\n * \"update\". `Grafana.AlertRuleGroup` is still the group as the unit BY DESIGN (that file's own\n * header) — this does not refuse the write, only makes the loss visible.\n *\n * ★ `Effect.logWarning`, NEVER A REFUSAL — mirrors the house pattern `proxmox/unreadable-read.ts`'s\n * `unreadableWarning` established. Alchemy's `Diff` type is exactly `NoopDiff | UpdateDiff |\n * ReplaceDiff` (no fourth action to carry \"update, but lossy\" through to `bun run plan`'s printed\n * action), and refusing here would contradict \"the group is the unit\": a whole-group replacement\n * dropping an out-of-band rule is EXPECTED behavior for this resource, not an error condition —\n * only a silent one worth surfacing loudly.\n *\n * ★ NO IMPORT OF `AlertRuleGroupProps` — deliberately primitive arguments (`folderUid`/`group`/a\n * plain `Set` of declared uids) rather than the whole props object, so this file has no\n * dependency back on `alert-rule-group.ts` and can be unit-tested with plain data.\n */\nimport * as Effect from 'effect/Effect';\n\nexport const warnOnDroppedRules = (\n folderUid: string,\n group: string,\n declaredUids: ReadonlySet<string>,\n liveRules: ReadonlyArray<{ readonly uid?: unknown; readonly title?: unknown }> | undefined,\n): Effect.Effect<void> =>\n Effect.gen(function* () {\n const dropped = (liveRules ?? [])\n .filter((rule): rule is { title?: unknown; uid: string } => typeof rule.uid === 'string')\n .filter((rule) => !declaredUids.has(rule.uid));\n if (dropped.length === 0) return;\n const names = dropped\n .map((rule) => `${typeof rule.title === 'string' ? rule.title : '(untitled)'} (${rule.uid})`)\n .join(', ');\n yield* Effect.logWarning(\n `Grafana.AlertRuleGroup ${folderUid}/${group}: this update REMOVES ${dropped.length} ` +\n `rule(s) not in the declaration: ${names}. Whole-group replacement is by design — add ` +\n `them to the declaration to keep them, or give them their own group.`,\n );\n });\n",
7
7
  "/**\n * Pure functions over one declared alert rule within a `Grafana.AlertRuleGroup` — no SDK call, no\n * Effect. Split out of `alert-rule-group.ts` the same way `dashboard-model.ts` is split out of\n * `dashboard.ts`: keeps that file under the house's 250-line cap, and lets the volatile-field\n * normalization be exercised directly in a test without a fake Grafana in the way.\n */\nimport type * as grafana from '@distilled.cloud/grafana';\n\n/** One declared rule — the SDK's own `ProvisionedAlertRuleInput` shape, minus the three fields\n * this resource derives from the GROUP itself (never declared per-rule) and `uid` widened from\n * optional to required — see alert-rule-group.ts's file header for the uid-required doctrine. */\nexport type AlertRuleInput = Omit<\n grafana.ProvisionedAlertRuleInput,\n 'folderUID' | 'orgID' | 'ruleGroup' | 'uid'\n> & { uid: string };\n\n/** Grafana injects/reassigns these on every write; a declared rule never sets them meaningfully.\n * MEASURED against `ProvisionedAlertRule` (services/grafana.ts): `id` is the internal numeric row\n * id, `updated` a server-set timestamp — neither exists on `ProvisionedAlertRuleInput` (the WRITE\n * shape) at all, only on the READ shape, confirming both are Grafana-managed, not declarable.\n * `provenance` is likewise read-only, but handled separately by `alerting-provenance.ts`'s\n * refusal rather than compared here: an object this family just wrote reads back with\n * `provenance: \"api\"`, which the DECLARATION never sets, so comparing it here would show a false\n * `update` on every rule this family itself owns — the refusal already gives it the attention it\n * needs, before this comparison ever runs. */\nconst RULE_VOLATILE_FIELDS = ['id', 'updated', 'provenance'] as const;\n\n/** `folderUID`/`ruleGroup`/`orgID` are forced to the group's own values (mirrors\n * `dashboard-model.ts`'s `normalizeModel` forcing `uid`) — a rule's declaration never repeats its\n * own group/folder, and a rule pasted from Grafana's own export always embeds whatever it read at\n * export time, which forcing to canonical values makes comparable regardless.\n * ⚠️ `orgID` DEFAULTS TO `1` — NOT MEASURED against a multi-org instance. Every Grafana instance\n * this house runs is single-org (grafana.md's own credentials section has no org-selecting\n * example); `GrafanaTarget.orgId` exists for a future multi-org target but a rule's own spec\n * functions have no access to it (unlike credentials, it is not ambient context here). A\n * multi-org declaration would need an explicit `orgID` prop added to `AlertRuleInput` — not\n * attempted here since no live target needs it yet. */\nexport const normalizeRule = (\n rule: Record<string, unknown>,\n folderUid: string,\n group: string,\n): Record<string, unknown> => {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(rule)) {\n if (key === 'folderUID' || key === 'ruleGroup' || key === 'orgID') continue;\n if ((RULE_VOLATILE_FIELDS as readonly string[]).includes(key)) continue;\n out[key] = value;\n }\n out.folderUID = folderUid;\n out.ruleGroup = group;\n out.orgID = 1;\n return out;\n};\n\n/** The full wire body for one rule on `routePutAlertRuleGroup` — the group-derived fields filled\n * in, `orgID` defaulted per the note above. */\nexport const toWireRule = (\n rule: AlertRuleInput,\n folderUid: string,\n group: string,\n): grafana.ProvisionedAlertRuleInput => ({\n ...rule,\n folderUID: folderUid,\n orgID: 1,\n ruleGroup: group,\n});\n",
8
8
  "/**\n * The shared refusal for a foreign-provenance ALERTING-PROVISIONING object — `Grafana.ContactPoint`,\n * `Grafana.MessageTemplate`, `Grafana.AlertRuleGroup` and `Grafana.NotificationPolicy` each read a\n * `provenance` string off what Grafana returns (`EmbeddedContactPoint.provenance`,\n * `NotificationTemplate.provenance`, `ProvisionedAlertRule.provenance` per rule, `Route.provenance`\n * on the policy tree — all measured against `@distilled.cloud/grafana`'s generated types,\n * `packages/distilled-grafana/src/services/grafana.ts`) and refuse a write when it disagrees with\n * what this family is allowed to own. Sibling to `provisioned.ts`, not a rename of it — the two\n * refusals guard different fields with different value shapes (`managedBy`/`provisioned` there,\n * `provenance` here) for two different Grafana API surfaces (classic folder/dashboard vs. alerting\n * provisioning), but both end in the SAME tagged error, reused from `provisioned.ts` rather than\n * declared twice: \"a write was refused because something else owns this object\" is one condition\n * across the whole family, the spirit PR 245's provisioned refusal already established.\n *\n * ★ THE ALLOWLIST, MEASURED AGAINST GRAFANA'S OWN SOURCE (not this SDK, which only echoes the\n * value back on read — never re-fetched live in this PR): Grafana's `pkg/services/ngalert/\n * models` package defines a `Provenance` type with `ProvenanceNone = \"\"` (nothing has claimed\n * the object — fresh, or written through the classic non-provisioning path), `ProvenanceAPI =\n * \"api\"` (created or last written through THIS provisioning API — what this family's own\n * create/update leaves behind), `ProvenanceFile = \"file\"` (Grafana's file-based provisioning),\n * and `ProvenanceConvertedPrometheus = \"converted_prometheus\"` (the Prometheus-rules importer).\n * Corroborated by Grafana's own docs (grafana.com/docs/grafana/v13.1/alerting/set-up/\n * provision-alerting-resources/http-api-provisioning/), whose example payloads show\n * `\"provenance\": \"api\"` on an alert rule this API created and `\"provenance\": \"file\"` on a\n * file-provisioned mute timing and template.\n *\n * `WRITABLE_PROVENANCES` is therefore an ALLOWLIST of `{\"\", \"api\"}`, not a denylist of the two\n * named foreign values — a provenance source not yet named above (a plugin importer, a future\n * Grafana release) refuses by default instead of silently being treated as writable, the safer\n * failure direction for a control-plane write.\n *\n * ⛔ A MISSING `provenance` FIELD IS TREATED AS FOREIGN, NEVER AS `ProvenanceNone` — fixed after an\n * adversarial review of this PR found the first version failed OPEN: every resource mapped\n * `live.provenance ?? ''`, and `''` (`ProvenanceNone`, writable) is indistinguishable from a\n * field the response simply never included once both collapse through `??`. Every `provenance`\n * field in this family is optional on the wire (`EmbeddedContactPoint.provenance?: string`, etc.\n * — genuinely absent is a real, typed possibility, not a hypothetical), and `Grafana.MuteTiming`'s\n * depends on an unmodeled-key passthrough this family has never observed against a real Grafana\n * response (see its own file header) — a version, edge case or bug in that decode path that drops\n * the field would, under the old `?? ''` rule, silently make a file-provisioned object look\n * writable. `isForeignProvenance`/`refuseIfForeignProvenance` below keep `undefined` as its own\n * value all the way through: ONLY a field Grafana explicitly reported as `\"\"` or `\"api\"` is\n * writable; missing entirely refuses, with a message that says so rather than naming a fabricated\n * provenance value.\n *\n * ⚠️ CLIENT-SIDE DEFENSE, NOT THE ONLY GUARD — AND NOT RE-MEASURED LIVE IN THIS PR. Grafana's own\n * alerting provisioning API server ALSO enforces this (unlike the classic folder/dashboard write\n * API `provisioned.ts` guards, which has no such server-side check at all): grafana/grafana#103597\n * (\"Unable to delete file provisioned alert rules\") reports exactly this block firing for a\n * `file`-provenance object, and the `X-Disable-Provenance` header's own documented purpose is \"by\n * default, you cannot edit API-provisioned alerting resources in Grafana\" (same doc page). This\n * function exists anyway, for the same reason `provisioned.ts` does: a clear, typed, house error\n * instead of whatever 400-with-a-string-message Grafana's server happens to return this version —\n * and as a defense against the known server-side bug that same issue documents\n * (`X-Disable-Provenance` failing to actually unlock a `file`-provenance object), which could\n * otherwise leave a write silently rejected with only a generic `BadRequest` and no explanation\n * of why.\n *\n * ⚠️ `Grafana.MuteTiming` ALSO USES THIS FUNCTION, BUT THROUGH A WIDENED LIVE TYPE — the SDK's\n * generated `MuteTimeInterval` interface (the TS type for both `GET .../mute-timings` and\n * `GET .../mute-timings/{name}`) declares no `provenance` field at all, unlike every other type\n * named above. A first pass at this family assumed that meant the DATA was gone; it is not —\n * MEASURED (see mute-timing.ts's own file header for the full account): `@distilled.cloud/core`'s\n * response decoding never runs a strict schema decode, only `JSON.parse` + a key-rename pass that\n * passes any key a type doesn't model through verbatim, so `provenance` survives on the actual\n * runtime value even though the TS type doesn't know about it. `mute-timing.ts` reads it through\n * a small local `& { provenance?: string }` intersection type rather than the SDK's own.\n */\nimport * as Effect from 'effect/Effect';\nimport { GrafanaProvisionedObjectError } from './provisioned.ts';\n\nexport { GrafanaProvisionedObjectError };\n\nconst WRITABLE_PROVENANCES = new Set(['', 'api']);\n\n/**\n * True when `provenance` names an owner other than \"this API\" — INCLUDING when Grafana did not\n * report the field at all (`undefined`). `undefined` is deliberately NEVER folded into `''`\n * (`ProvenanceNone`) here — see the file header's \"fails open\" note. Only a value Grafana\n * explicitly reported as `\"\"` or `\"api\"` is writable.\n */\nexport const isForeignProvenance = (provenance: string | undefined): boolean =>\n provenance === undefined || !WRITABLE_PROVENANCES.has(provenance);\n\nexport const refuseIfForeignProvenance = (\n kind:\n | 'Grafana.ContactPoint'\n | 'Grafana.MessageTemplate'\n | 'Grafana.MuteTiming'\n | 'Grafana.AlertRuleGroup'\n | 'Grafana.NotificationPolicy',\n id: string,\n provenance: string | undefined,\n): Effect.Effect<never, GrafanaProvisionedObjectError> => {\n const reason =\n provenance === undefined\n ? `did not report a provenance at all — this family cannot tell whether it is safe to own`\n : `has provenance '${provenance}', not '(none)' or 'api'`;\n return Effect.fail(\n new GrafanaProvisionedObjectError({\n message:\n `${kind} '${id}' ${reason} — something other than this API may own it (file ` +\n `provisioning, the Prometheus-rules importer, or similar), and writing here could take ` +\n `over or corrupt an object this family does not actually control. Edit it at its actual ` +\n `source instead — declaring this object read-only (a declaration matching what is live) ` +\n `is safe and will never reach this refusal.`,\n }),\n );\n};\n",
9
- "/**\n * The shared refusal for a file-provisioned Grafana object — `Grafana.Folder` and\n * `Grafana.Dashboard` both carry a live signal Grafana itself treats as read-only through the\n * classic write API this family calls: `Folder.managedBy` (non-empty when something other than\n * this API manages the folder — provisioning is the case this house cares about, but the field\n * itself is Grafana's general \"who owns this\" marker) and `DashboardMeta.provisioned` (paired\n * with `provisionedExternalId`, the file path). A declaration must never attempt a write against\n * either — see docs/grafana-folder-dashboard.md's \"provisioned objects\" section.\n *\n * ⚠️ THE EXACT `managedBy` VALUES ARE INFERRED FROM THE SDK's SCHEMA, NOT MEASURED. No live\n * instance in this house currently has a file-provisioned FOLDER to read (docs/grafana.md:\n * `teslamate-grafana` has none at all; the mini's Grafana provisions dashboards, not folders) and\n * this PR makes no live calls. `Folder.managedBy` and `DashboardMeta.provisioned` are exactly\n * the fields the OpenAPI schema types for this purpose — treat any non-empty `managedBy` as\n * provisioned rather than special-casing specific string values that were never observed live.\n *\n * ⛔ ADOPTING A PROVISIONED OBJECT IS STILL FINE. `read`/`reconcile`'s no-write \"already converged\"\n * path (resource.ts) never calls `create`/`update`/`destroy` at all when the declaration already\n * matches what is live — only an actual attempted WRITE against a provisioned object is refused,\n * by the two callers of this function inside folder.ts/dashboard.ts's own `update`/`destroy`.\n */\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\n\nexport class GrafanaProvisionedObjectError extends Data.TaggedError(\n 'GrafanaProvisionedObjectError',\n)<{\n readonly message: string;\n}> {}\n\nexport const refuseIfProvisioned = (\n kind: 'Grafana.Folder' | 'Grafana.Dashboard',\n uid: string,\n owner: string | undefined,\n): Effect.Effect<never, GrafanaProvisionedObjectError> => {\n const ownerClause =\n owner === undefined || owner === ''\n ? `(this Grafana instance did not report an owning file)`\n : `by ${owner}`;\n return Effect.fail(\n new GrafanaProvisionedObjectError({\n message:\n `${kind} '${uid}' is file-provisioned ${ownerClause} and read-only through the classic ` +\n `write API this family calls. Edit the provisioning file instead — declaring this ` +\n `object read-only (a declaration matching what is live) is safe and will never reach ` +\n `this refusal.`,\n }),\n );\n};\n",
9
+ "/**\n * The shared refusal for a file-provisioned Grafana object — `Grafana.Folder` and\n * `Grafana.Dashboard` both carry a live signal Grafana itself treats as read-only through the\n * classic write API this family calls: `Folder.managedBy` (non-empty when something other than\n * this API manages the folder — provisioning is the case this house cares about, but the field\n * itself is Grafana's general \"who owns this\" marker) and `DashboardMeta.provisioned` (paired\n * with `provisionedExternalId`, the file path). A declaration must never attempt a write against\n * either — see docs/grafana-folder-dashboard.md's \"provisioned objects\" section.\n *\n * ⚠️ THE EXACT `managedBy` VALUES ARE INFERRED FROM THE SDK's SCHEMA, NOT MEASURED. No live\n * instance in this house currently has a file-provisioned FOLDER to read (docs/grafana.md:\n * `teslamate-grafana` has none at all; the mini's Grafana provisions dashboards, not folders) and\n * this PR makes no live calls. `Folder.managedBy` and `DashboardMeta.provisioned` are exactly\n * the fields the OpenAPI schema types for this purpose — treat any non-empty `managedBy` as\n * provisioned rather than special-casing specific string values that were never observed live.\n *\n * ⛔ ADOPTING A PROVISIONED OBJECT IS STILL FINE. `read`/`reconcile`'s no-write \"already converged\"\n * path (resource.ts) never calls `create`/`update`/`destroy` at all when the declaration already\n * matches what is live — only an actual attempted WRITE against a provisioned object is refused,\n * by the two callers of this function inside folder.ts/dashboard.ts's own `update`/`destroy`.\n */\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\n\nexport class GrafanaProvisionedObjectError extends Data.TaggedError(\n 'GrafanaProvisionedObjectError',\n)<{\n readonly message: string;\n}> {}\n\nexport const refuseIfProvisioned = (\n kind: 'Grafana.Folder' | 'Grafana.Dashboard' | 'Grafana.Team',\n uid: string,\n owner: string | undefined,\n): Effect.Effect<never, GrafanaProvisionedObjectError> => {\n const ownerClause =\n owner === undefined || owner === ''\n ? `(this Grafana instance did not report an owning file)`\n : `by ${owner}`;\n return Effect.fail(\n new GrafanaProvisionedObjectError({\n message:\n `${kind} '${uid}' is file-provisioned ${ownerClause} and read-only through the classic ` +\n `write API this family calls. Edit the provisioning file instead — declaring this ` +\n `object read-only (a declaration matching what is live) is safe and will never reach ` +\n `this refusal.`,\n }),\n );\n};\n",
10
10
  "/**\n * One shape for every Grafana object this family declares — mirroring `../forgejo/resource.ts`\n * and `../netbox/resource.ts` exactly, minus the credentials wrapping those two bake in.\n *\n * ★ CREDENTIALS ARE NOT PROVIDED HERE. Forgejo and NetBox each manage exactly one instance for\n * this house, so their engines close over a hardcoded `CredentialsFromEnv`. Grafana does not —\n * see `credentials.ts`'s note on `grafana.homeflare.dev` vs `teslamate-grafana` — so `Credentials`\n * stays a context requirement on every handler here, and `providers.ts`'s `grafanaProviders`\n * supplies it per target with `Layer.provide`, the same composition `litellm/providers.ts` uses.\n *\n * ⚠️ `NotFound` IS FOLDED TO \"ABSENT\" INSIDE EACH RESOURCE FILE'S OWN `fetchLive`, NOT HERE — the\n * same split forgejo's and netbox's engines use. `Effect.catchTag`'s tag-literal inference needs\n * a concrete error union to resolve `\"NotFound\"` against; a spec's `E` is only concrete at each\n * resource file's own call site.\n */\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport type { GrafanaOpContext } from '@distilled.cloud/grafana/Protocol';\nimport * as Effect from 'effect/Effect';\n\n/**\n * One Grafana object's distilled calls. `Live` is whatever the SDK decodes (a `DataSource`, …) —\n * no untyped `Record<string, unknown>`. `E` is left to each resource file to declare (the union\n * of the distilled operations it actually calls plus any domain refusal, e.g. an unset secret-ref\n * env var), so a call site's precise error union flows straight through instead of being widened\n * by hand here.\n */\nexport type GrafanaSpec<Props extends object, Live, Attributes, E> = {\n /** Already folds the SDK's `NotFound` to `undefined` via its own `catchTag` — see the note above. */\n readonly fetchLive: (props: Props) => Effect.Effect<Live | undefined, E, GrafanaOpContext>;\n readonly attributes: (live: Live, props: Props) => Attributes | undefined;\n readonly matches: (attributes: Attributes, props: Props) => boolean;\n readonly create: (props: Props) => Effect.Effect<unknown, E, GrafanaOpContext>;\n readonly update?: (props: Props, live: Live) => Effect.Effect<unknown, E, GrafanaOpContext>;\n readonly destroy: (props: Props, live: Live) => Effect.Effect<unknown, E, GrafanaOpContext>;\n};\n\nexport const grafanaOperations = <Props extends object, Live, Attributes, E>(\n spec: GrafanaSpec<Props, Live, Attributes, E>,\n) => {\n const read = (props: Props) =>\n spec\n .fetchLive(props)\n .pipe(Effect.map((live) => (live === undefined ? undefined : spec.attributes(live, props))));\n\n return {\n read,\n\n diff: (news: Input<Props>, output: Attributes | undefined) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* read(news);\n if (live === undefined) return { action: 'update' } as const;\n if (spec.matches(live, news)) return { action: 'noop' } as const;\n return spec.update === undefined\n ? ({ action: 'replace' } as const)\n : ({ action: 'update' } as const);\n }),\n\n /**\n * ★ OBSERVES BEFORE IT WRITES (S9, S10) — THE WHOLE OF \"ADOPT\" FOR THIS FAMILY. A `uid` this\n * Grafana instance already has is bound and, when it already matches the declaration,\n * left alone; only a genuinely absent `uid` is created. Declaring exactly what is live\n * changes nothing on `reconcile`, the same posture netbox/resource.ts documents as\n * \"adopt is the default posture, not a flag\".\n */\n reconcile: (news: Props) =>\n Effect.gen(function* () {\n const before = yield* spec.fetchLive(news);\n if (before === undefined) {\n yield* spec.create(news);\n } else if (spec.update !== undefined) {\n const mapped = spec.attributes(before, news);\n if (mapped === undefined || spec.matches(mapped, news)) {\n /* adoption or already converged — no write */\n } else {\n yield* spec.update(news, before);\n }\n }\n const after = yield* read(news);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(\n 'grafanaOperations: the write returned no error but the object is still absent. ' +\n 'Read back rather than trusting the response status.',\n ),\n );\n }\n return after;\n }),\n\n destroy: (olds: Props) =>\n Effect.gen(function* () {\n const live = yield* spec.fetchLive(olds);\n if (live === undefined) return;\n yield* spec.destroy(olds, live);\n }),\n };\n};\n\n/**\n * The five provider handlers for a spec'd Grafana object, wired once. `Credentials` and\n * `HttpClient.HttpClient` stay ambient context requirements — see the file header.\n *\n * ⚠️ `list` answers empty — an org's full datasource list is not a page this family sweeps for\n * adoption; adoption stays explicit, the same reasoning forgejo's and netbox's engines give.\n */\nexport const grafanaHandlers = <Props extends object, Live, Attributes extends object, E>(\n spec: GrafanaSpec<Props, Live, Attributes, E>,\n) => {\n const ops = grafanaOperations(spec);\n return {\n list: () => Effect.succeed([]),\n read: ({ olds }: { olds: Props }) => ops.read(olds),\n diff: ({ news, output }: { news: Input<Props>; output: Attributes | undefined }) =>\n ops.diff(news, output),\n reconcile: ({ news }: { news: Props }) => ops.reconcile(news),\n delete: ({ olds }: { olds: Props }) => ops.destroy(olds),\n };\n};\n",
11
11
  "/**\n * `declaredContentMatches` — \"is the declaration a subset of what is live\", not plain equality.\n * Extracted out of `dashboard-model.ts` (where it was introduced, after an adversarial review of\n * that PR found plain structural equality made an ordinary, never-edited dashboard show `update`\n * FOREVER) once a second shape needed the identical rule: `Grafana.ContactPoint`'s `settings` is\n * the same story — Grafana can inject default fields into a contact point's settings that the\n * declaration never mentioned, and `Grafana.AlertRuleGroup`'s per-rule `data`/`annotations`/\n * `labels` maps carry the same risk. Nothing about the reasoning below is dashboard-specific;\n * `dashboard-model.ts` now just re-exports this.\n *\n * ★ `declared` NEED ONLY BE A SUBSET OF `live`. Grafana's own save/decode path can decorate an\n * object with fields the declaration never set (a dashboard panel's auto-resolved `datasource`\n * reference is the documented example dashboard-model.ts found — Grafana's schema migration\n * decorates any panel/target whose `datasource` is absent with an explicit `{type, uid}`\n * reference on save). This function instead asks only \"does every field the DECLARATION\n * mentions, at any depth, still match what is live\" — `live` may carry additional fields, at any\n * depth, that `declared` never mentioned, without being compared at all. A field `declared` DOES\n * mention that is missing, or different, in `live` still fails the match — real content drift is\n * still caught exactly as before; only fields the declaration is silent about are now tolerated.\n *\n * ⚠️ THE TRADE-OFF THIS ACCEPTS, DELIBERATELY: removing a field from the declaration (rather than\n * changing its value) can no longer force Grafana to drop it. If a previous declaration set a\n * field and a later one deletes that key entirely, `live` keeps whatever the last write set — the\n * declaration is silent about that key now, so nothing compares it, so no `update` ever fires to\n * change it. This is the same \"undeclared means don't care, never means force-to-default\"\n * convention already used everywhere else in this kit for a plain optional prop; it now also\n * applies inside a nested JSON value, not just at the top-level props. Declare an explicit\n * replacement value to change a field; omission never clears one that was set by a previous\n * declaration or by Grafana itself.\n *\n * ⚠️ ARRAYS COMPARE BY LENGTH, THEN ELEMENT-WISE SUBSET — never a looser \"declared has fewer\n * items\" rule. A caller whose array IS order-significant (dashboard `panels`/`targets`) or\n * position-keyed (an alert rule group's `rules`) gets that for free; a caller with a genuinely\n * unordered array would need its own normalization first (this file has no `sortedSet`, and\n * nothing in this kit's Grafana family needs one — see dashboard-model.ts's own note).\n *\n * ⛔ NOT RE-MEASURED FOR EVERY CALLER — flagged by an adversarial review of this PR. The exact\n * length rule is confirmed for dashboards (the original, documented case), but whether Grafana\n * ever PADS or APPENDS a default entry to an array the way it decorates an object field (the\n * `datasource` auto-decoration above) is unverified for `Grafana.MuteTiming`'s `time_intervals`\n * specifically — no live mute timing exists in this house to observe (grafana.md's census), and\n * `mute-timing.test.ts`'s own fixtures are hand-authored, not captured. If a future live\n * observation finds Grafana appending an entry (e.g. a normalized default time range) to a\n * declared `time_intervals` array, the length check here would show a permanent false `update` —\n * the exact regression this whole file exists to prevent for OBJECT fields already. `mute-timing.\n * test.ts`'s \"array length is exact, not tolerant\" test pins today's behavior so that fix has an\n * obvious, single place to change (relax this rule, or give the mute-timing caller its own\n * length-tolerant wrapper) rather than being rediscovered from scratch.\n * ⚠️ `null` ON EITHER SIDE OF A LEAF NEVER MISMATCHES (mirrors `alchemy/Diff`'s `deepEqual` with\n * `stripNullish: true`, which this function replaces wherever a caller needs subset semantics).\n */\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const declaredContentMatches = (declared: unknown, live: unknown): boolean => {\n if (declared == null) return true;\n if (Array.isArray(declared)) {\n return (\n Array.isArray(live) &&\n declared.length === live.length &&\n declared.every((item, index) => declaredContentMatches(item, live[index]))\n );\n }\n if (isPlainObject(declared)) {\n return (\n isPlainObject(live) &&\n Object.entries(declared).every(([key, value]) => declaredContentMatches(value, live[key]))\n );\n }\n return declared === live;\n};\n",
12
12
  "/**\n * `Grafana.NotificationPolicy` — the notification policy tree. A SINGLETON: `GET`/`PUT`\n * `/v1/provisioning/policies` always address the ONE tree an instance has, there is no path\n * parameter, and `RouteGetPolicyTreeError` is `Forbidden | GrafanaOpError` — no `NotFound` case at\n * all, MEASURED. `fetchLive` therefore NEVER returns `undefined`: this resource has no create and\n * no delete in the sense every other resource in this family does — `reconcile`'s `before ===\n * undefined` branch (`resource.ts`) is dead code here, and `create` below exists only because\n * `GrafanaSpec.create` is a required field on the shared type, not because it is ever reached.\n * \"Declaring\" this resource means ADOPTING whatever tree is live and then keeping it in sync —\n * never creating or destroying the tree itself, only ever `PUT`-replacing its contents.\n *\n * ⛔ `routeResetPolicyTree` IS NEVER CALLED UNLESS `allowReset: true` IS EXPLICITLY DECLARED — a\n * second, independent gate on top of `defaultRemovalPolicy: 'retain'` below. Alchemy's own\n * removal-policy gate decides whether the engine calls this resource's `delete` handler AT ALL\n * (retain means it never does, unless a stack opts in with `.pipe(RemovalPolicy.destroy())` —\n * the convention every `Bao.*`/`Grafana.Folder`/`Grafana.AlertRuleGroup` family member already\n * uses); `allowReset` is a SEPARATE prop-level gate inside `destroy` itself, so even a stack that\n * opted into destroy at the Alchemy level still needs this resource's own explicit opt-in before\n * it will reset. Two gates, not one, because `routeResetPolicyTree` is uniquely destructive among\n * everything this family calls: it wipes every declared route, receiver reference and matcher\n * back to Grafana's own bare default in one call, for the WHOLE instance, not one object. Without\n * `allowReset`, `destroy` logs a warning and returns — retained, not reset.\n *\n * ★ PUT REPLACES THE WHOLE TREE — A DROPPED SUB-ROUTE IS WARNED ABOUT, NEVER SILENT. Same shape as\n * kit PR 254's `Grafana.AlertRuleGroup` fix (an adversarial review of that PR found the identical\n * risk for rule groups): `notification-policy-drop-warning.ts`'s `warnOnDroppedRoutes`, called\n * from both this resource's custom `diff` (so `bun run plan` shows it before anything is\n * written) and from `update` itself.\n *\n * ⛔ ROUTE ORDER IS SIGNIFICANT — NEVER REORDERED. Same as `Grafana.AlertRuleGroup`'s rules:\n * `subset-match.ts`'s array comparison is position-significant, and Alertmanager itself routes\n * an alert to the FIRST matching route in array order — reordering routes is a genuine routing\n * change, not cosmetic.\n *\n * ⛔ A FOREIGN-PROVENANCE TREE REFUSES EVERY UPDATE — `alerting-provenance.ts`, unchanged from kit\n * PR 250/254 (including the missing-means-foreign fix: `Route.provenance` is optional on the\n * wire, and `undefined` is never folded into `\"\"`). `create` is never at risk — see above, it is\n * unreachable.\n *\n * ⚠️ GRAFANA-INJECTED DEFAULTS ARE TOLERATED THE `declaredContentMatches` WAY, NOT HAND-NORMALIZED\n * — `matches()` below runs the (volatile-field-stripped) declared and live trees through\n * `subset-match.ts`'s tolerant-subset comparison, the same mechanism `Grafana.Dashboard`'s\n * panel-`datasource` auto-decoration and `Grafana.ContactPoint`'s settings defaults already rely\n * on: a live tree may carry additional fields, at any depth, the declaration never mentioned\n * (Grafana injecting a default `group_wait`/`group_interval`/`repeat_interval`/`group_by: []`\n * when the declaration omits them is the plausible case) without failing the match. ⚠️ NOT\n * MEASURED against a live instance — no live policy tree exists in this house to read (no live\n * calls in this PR either) — this is the documented, conservative default every unmeasured value\n * shape in this family takes, not a guess dressed up as a fact.\n *\n * ⚠️ `X-Disable-Provenance` IS NEVER SET — same reasoning as `contact-point.ts`'s file header.\n */\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Effect from 'effect/Effect';\nimport {\n type GrafanaProvisionedObjectError,\n isForeignProvenance,\n refuseIfForeignProvenance,\n} from './alerting-provenance.ts';\nimport { type PolicyRoute, normalizeRoute } from './notification-policy-model.ts';\nimport { warnOnDroppedRoutes } from './notification-policy-drop-warning.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\nimport { declaredContentMatches } from './subset-match.ts';\n\nexport type { PolicyRoute };\n\nexport interface NotificationPolicyProps {\n /** The root route and its full nested tree — Grafana's `Route` shape (`receiver`, `group_by`,\n * `matchers`, nested `routes[]`, …), passed through opaquely — see the file header. Order of\n * `routes[]` at every level is significant. */\n route: PolicyRoute;\n /** Lets `destroy` actually call `routeResetPolicyTree`. Defaults to `false` — see the file\n * header for why this is a second gate on top of Alchemy's own removal policy. */\n allowReset?: boolean;\n}\n\nexport interface NotificationPolicyAttributes {\n route: PolicyRoute;\n /** `\"\"`/`\"api\"` (this family may write); anything else, INCLUDING `undefined`, refuses — see\n * alerting-provenance.ts's \"fails open\" note. */\n provenance: string | undefined;\n}\n\nexport interface GrafanaNotificationPolicy extends Resource<\n 'Grafana.NotificationPolicy',\n NotificationPolicyProps,\n NotificationPolicyAttributes,\n never\n> {}\n\nexport const GrafanaNotificationPolicy = Resource<GrafanaNotificationPolicy>(\n 'Grafana.NotificationPolicy',\n { defaultRemovalPolicy: 'retain' },\n);\n\nconst body = (props: NotificationPolicyProps) =>\n props.route as unknown as grafana.RoutePutPolicyTreeRequest;\n\nexport const spec: GrafanaSpec<\n NotificationPolicyProps,\n grafana.Route,\n NotificationPolicyAttributes,\n | grafana.RouteGetPolicyTreeError\n | grafana.RoutePutPolicyTreeError\n | grafana.RouteResetPolicyTreeError\n | GrafanaProvisionedObjectError\n> = {\n attributes: (live) => ({\n provenance: live.provenance,\n route: normalizeRoute(live as unknown as PolicyRoute),\n }),\n // ⚠️ UNREACHABLE IN PRACTICE — see the file header. Implemented as the same PUT `update` sends,\n // defensively, rather than `Effect.die`, in case a future Grafana version ever does answer\n // `NotFound` here; `GrafanaSpec.create` is required by the shared type either way.\n create: (props) => grafana.routePutPolicyTree(body(props)),\n destroy: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance(\n 'Grafana.NotificationPolicy',\n 'default',\n live.provenance,\n );\n }\n if (props.allowReset !== true) {\n yield* Effect.logWarning(\n 'Grafana.NotificationPolicy: destroy requested but allowReset is not set -- the policy ' +\n 'tree is RETAINED, not reset. Grafana always needs a root route; resetting wipes ' +\n \"every declared route/receiver/matcher back to Grafana's own default for the WHOLE \" +\n 'instance. Set allowReset: true to actually call routeResetPolicyTree.',\n );\n return;\n }\n yield* grafana.routeResetPolicyTree({});\n }),\n fetchLive: (_props) => grafana.routeGetPolicyTree({}),\n matches: (attributes, props) =>\n declaredContentMatches(normalizeRoute(props.route), attributes.route),\n update: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance(\n 'Grafana.NotificationPolicy',\n 'default',\n live.provenance,\n );\n }\n yield* warnOnDroppedRoutes(props.route, live as unknown as PolicyRoute);\n yield* grafana.routePutPolicyTree(body(props));\n }),\n};\n\n/**\n * ⚠️ A LOCAL REIMPLEMENTATION OF `resource.ts`'s GENERIC `diff`, NOT A WRAP OF IT — same reasoning\n * as `alert-rule-group.ts`'s own `diff`: the generic version has no seam to run the drop-warning\n * side effect against the live tree it reads, and wrapping it would mean a second live fetch\n * just to see what it already saw.\n */\nconst diff = ({\n news,\n output,\n}: {\n news: Input<NotificationPolicyProps>;\n output: NotificationPolicyAttributes | undefined;\n}) =>\n Effect.gen(function* () {\n if (output === undefined || !isResolved(news)) return undefined;\n const live = yield* spec.fetchLive(news);\n // ⚠️ UNREACHABLE IN PRACTICE — see the file header: `routeGetPolicyTree` has no `NotFound`\n // case, so `live` is never actually `undefined`. `GrafanaSpec.fetchLive`'s shared return\n // type is `Live | undefined` for every resource in the family, so this check exists purely\n // to satisfy that type, the same defensive stance `create` above takes.\n if (live === undefined) return { action: 'update' } as const;\n yield* warnOnDroppedRoutes(news.route, live as unknown as PolicyRoute);\n const mapped = spec.attributes(live, news);\n return mapped !== undefined && spec.matches(mapped, news)\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n });\n\nexport const handlers = { ...grafanaHandlers(spec), diff };\n\nexport const GrafanaNotificationPolicyProvider = () =>\n Provider.effect(\n GrafanaNotificationPolicy,\n Effect.succeed(GrafanaNotificationPolicy.Provider.of(handlers)),\n );\n",
@@ -17,13 +17,15 @@
17
17
  "/**\n * `Grafana.Dashboard` — one Grafana dashboard, keyed by `uid`. Same uid-required doctrine as\n * `datasource.ts`/`folder.ts` (`getDashboard`/`postDashboard`/`deleteDashboard` are all UID-keyed\n * on the wire — `postDashboard`'s own `uid` travels INSIDE the `dashboard` JSON body, not as a\n * request field, because Grafana's classic dashboard-save API has never had one; see\n * `dashboard-model.ts`'s `normalizeModel`, which is what puts it there).\n *\n * ★ THE DECLARED CONTENT IS THE DASHBOARD JSON MODEL — `DashboardProps.dashboard`, the same shape\n * Grafana's own \"Export as JSON\" produces. `dashboard-model.ts`'s `normalizeModel` strips the\n * volatile fields (`id`, `version`, `iteration`) and forces `uid` to this resource's own value\n * before ANY comparison, so a plan against an unchanged dashboard is a true noop despite those\n * fields moving on every live save — see that file for the full reasoning, including which\n * fields (`panels`, `targets`) are array-ORDER-significant and compared as such.\n *\n * ⛔ `matches` COMPARES \"IS THE DECLARATION A SUBSET OF WHAT IS LIVE\", NOT PLAIN EQUALITY —\n * `dashboard-model.ts`'s `declaredContentMatches`, added after an adversarial review of this PR\n * found plain `deepEqual` made an ordinary dashboard show `update` FOREVER: Grafana's own\n * schema-migration on save decorates any panel/target whose `datasource` is absent with an\n * explicit reference, so a declaration that never sets one would permanently disagree with what\n * it reads back. See that function's own header for the full reasoning and the trade-off it\n * accepts (an omitted field can no longer be used to CLEAR a previously-set one).\n *\n * ⛔ VERSION CONFLICTS (412) FAIL LOUDLY — NEVER OVERWRITTEN BLINDLY. `update` injects the\n * `version` this resource just read (`live.meta.version`, from the SAME `fetchLive` call\n * `resource.ts`'s `reconcile` already made before calling `update`) into the model it sends, and\n * `overwrite` is never set. If Grafana's own version check then still fails — someone else saved\n * in the gap between that read and this write — `postDashboard` answers `412` and\n * `PreconditionFailed` is left IN the error union below, uncaught: the whole reconcile fails, the\n * deploy stops, and nothing is written. The next run's `fetchLive` re-reads the new live version\n * fresh, which is the \"re-read\" half of \"re-read and fail loudly\" — there is no separate retry\n * loop in this file, because the next `plan`/`deploy` invocation already IS that re-read.\n *\n * ⛔ A PROVISIONED DASHBOARD (`meta.provisioned` — see provisioned.ts) REFUSES EVERY UPDATE AND\n * DESTROY, naming `meta.provisionedExternalId` (the file) when Grafana reports one. `matches`\n * still compares structurally regardless, so a mismatched declaration against a provisioned\n * dashboard shows `update` in a plan rather than a silent, permanently-hidden noop.\n *\n * ⚠️ NO RETAIN DEFAULT, UNLIKE `Grafana.Folder`. Deleting one dashboard is a single-object blast\n * radius — the same class `Grafana.Datasource` already accepts without a retain guard — not\n * folder.ts's multi-object cascade (a folder's delete takes its dashboards AND their alert rules\n * with it). See folder.ts's file header for the full contrast.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Effect from 'effect/Effect';\nimport {\n type DashboardModel,\n declaredContentMatches,\n modelTitle,\n normalizeModel,\n} from './dashboard-model.ts';\nimport { type GrafanaProvisionedObjectError, refuseIfProvisioned } from './provisioned.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\n\nexport type { DashboardModel };\n\nexport interface DashboardProps {\n uid: string;\n /** Omit for the General/root folder. */\n folderUid?: string;\n /** The dashboard JSON model — see the file header. `id`/`version`/`iteration`/`uid` inside it\n * are ignored; `uid` above is the single source of truth. */\n dashboard: DashboardModel;\n}\n\nexport interface DashboardAttributes {\n uid: string;\n title: string;\n version: number;\n folderUid: string;\n url: string;\n /** True when Grafana reports this dashboard as file-provisioned (read-only — see provisioned.ts). */\n provisioned: boolean;\n provisionedExternalId: string;\n /** The live model, normalized the same way `matches` compares it. */\n dashboard: DashboardModel;\n}\n\nexport interface GrafanaDashboard extends Resource<\n 'Grafana.Dashboard',\n DashboardProps,\n DashboardAttributes,\n never\n> {}\n\nexport const GrafanaDashboard = Resource<GrafanaDashboard>('Grafana.Dashboard');\n\nconst modelOf = (live: grafana.DashboardFullWithMeta): DashboardModel =>\n live.dashboard !== null && typeof live.dashboard === 'object'\n ? (live.dashboard as DashboardModel)\n : {};\n\nexport const spec: GrafanaSpec<\n DashboardProps,\n grafana.DashboardFullWithMeta,\n DashboardAttributes,\n | grafana.GetDashboardError\n | grafana.PostDashboardError\n | grafana.DeleteDashboardError\n | GrafanaProvisionedObjectError\n> = {\n attributes: (live, props) => {\n const model = normalizeModel(modelOf(live), props.uid);\n return {\n dashboard: model,\n folderUid: live.meta?.folderUid ?? '',\n provisioned: live.meta?.provisioned ?? false,\n provisionedExternalId: live.meta?.provisionedExternalId ?? '',\n title: modelTitle(model),\n uid: props.uid,\n url: live.meta?.url ?? '',\n version: live.meta?.version ?? 0,\n };\n },\n create: (props) =>\n grafana.postDashboard({\n dashboard: normalizeModel(props.dashboard, props.uid),\n ...(props.folderUid === undefined ? {} : { folderUid: props.folderUid }),\n }),\n destroy: (props, live) =>\n Effect.gen(function* () {\n if (live.meta?.provisioned) {\n return yield* refuseIfProvisioned(\n 'Grafana.Dashboard',\n props.uid,\n live.meta.provisionedExternalId,\n );\n }\n yield* grafana.deleteDashboard({ uid: props.uid });\n }),\n fetchLive: (props) =>\n grafana\n .getDashboard({ uid: props.uid })\n .pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n matches: (attributes, props) =>\n (props.folderUid === undefined || attributes.folderUid === props.folderUid) &&\n declaredContentMatches(normalizeModel(props.dashboard, props.uid), attributes.dashboard),\n update: (props, live) =>\n Effect.gen(function* () {\n if (live.meta?.provisioned) {\n return yield* refuseIfProvisioned(\n 'Grafana.Dashboard',\n props.uid,\n live.meta.provisionedExternalId,\n );\n }\n return yield* grafana.postDashboard({\n dashboard: {\n ...normalizeModel(props.dashboard, props.uid),\n ...(live.meta?.version === undefined ? {} : { version: live.meta.version }),\n },\n ...(props.folderUid === undefined ? {} : { folderUid: props.folderUid }),\n });\n }),\n};\n\nexport const handlers = grafanaHandlers(spec);\n\nexport const GrafanaDashboardProvider = () =>\n Provider.effect(GrafanaDashboard, Effect.succeed(GrafanaDashboard.Provider.of(handlers)));\n",
18
18
  "/**\n * Pure functions over a dashboard JSON model — no SDK call, no Effect. Split out of dashboard.ts\n * so that file stays under the house's 250-line cap, and so `normalizeModel`'s no-change-is-noop\n * behavior is exercised directly in dashboard-model.test.ts without a fake Grafana in the way.\n */\nexport type DashboardModel = Record<string, unknown>;\n\n/** Grafana injects or increments these on every save; a declared model never sets them meaningfully. */\nconst VOLATILE_FIELDS = ['id', 'version', 'iteration'] as const;\n\n/**\n * ★ NORMALIZES BOTH SIDES THE SAME WAY, so a no-change plan is a true noop\n * (docs/grafana-folder-dashboard.md). Strips `id`/`version`/`iteration` (Grafana-managed, never\n * declared content) and forces `uid` to this resource's OWN canonical value, wherever — or\n * whether — the source object carried one. That second part is \"uid placement\": a dashboard\n * pasted from Grafana's own \"Export as JSON\" always embeds the OLD live uid (or none, for a\n * never-saved dashboard), while the live model this resource reads back always carries the\n * CURRENT one; forcing both to `props.uid` before comparing is what makes those two shapes equal\n * instead of permanently disagreeing on one field neither side is meant to declare independently\n * (`DashboardProps.uid` — see dashboard.ts — is the single source of truth).\n *\n * ⚠️ EVERY OTHER DECLARED FIELD COMPARES STRUCTURALLY, ARRAY ORDER INCLUDED — dashboard.ts's\n * `matches` runs this output through THIS FILE's own `declaredContentMatches` (below), which\n * never reorders an array. That is correct here: `panels` is position-significant (screen layout\n * via its own `gridPos`, but the array order also drives Grafana's internal panel indexing and\n * any `repeat` behavior) and each panel's `targets` is execution/legend order. Nothing in a\n * dashboard model is a genuinely unordered SET the way UniFi's `trustedDhcpServerIpAddresses` is\n * (unifi/network-form.ts's `sortedSet`) — this family has no field that needs one.\n * ⚠️ `schemaVersion` IS DELIBERATELY **NOT** NORMALIZED — NOT MEASURED against a live instance (no\n * live calls in this PR). Community reports say Grafana can rewrite an old dashboard's\n * `schemaVersion` upward on load; IF that also happens on every plain save of an\n * already-current-schema dashboard, every plan against it would show a false `update` forever —\n * but silently normalizing it away on a guess would just as easily hide a genuine schema\n * mismatch. Left comparing until measured: add it to `VOLATILE_FIELDS` with a dated, measured\n * comment the day it is seen live, the same standard every other row in this file meets.\n */\nexport const normalizeModel = (model: DashboardModel, uid: string): DashboardModel => {\n const normalized: DashboardModel = {};\n for (const [key, value] of Object.entries(model)) {\n if (key === 'uid') continue;\n if ((VOLATILE_FIELDS as readonly string[]).includes(key)) continue;\n normalized[key] = value;\n }\n normalized.uid = uid;\n return normalized;\n};\n\n/** The model's own declared title — reporting only. It is never compared on its own; the whole\n * normalized model is, in dashboard.ts's `matches`, so a title-only mismatch still shows `update`. */\nexport const modelTitle = (model: DashboardModel): string =>\n typeof model.title === 'string' ? model.title : '';\n\n/**\n * `declared` need only be a subset of `live` — dashboard.ts's `matches` runs `normalizeModel`'s\n * output through this. Moved to `subset-match.ts` once `Grafana.ContactPoint`'s `settings` needed\n * the identical \"declaration silent about a field means don't compare it\" rule; re-exported here\n * under its original name so this file's own callers and dashboard-model.test.ts are unchanged.\n * See subset-match.ts for the full reasoning, including the regression this exists to fix\n * (Grafana's dashboard-save schema migration auto-decorating a panel's `datasource`) and the\n * trade-off it accepts (an omitted field can no longer force-clear a previously-set one).\n */\nexport { declaredContentMatches } from './subset-match.ts';\n",
19
19
  "/**\n * `Grafana.Folder` — one Grafana folder, keyed by `uid`. Mirrors `datasource.ts`'s shape and\n * doctrine (uid required, not generated — same reasoning, `getFolderByUID`/`updateFolder`/\n * `deleteFolder` are all UID-keyed and `getFolders` (list) has no per-uid filter).\n *\n * ⛔ `description` IS WRITE-ONLY — MEASURED against `@distilled.cloud/grafana`'s generated types\n * (`Folder` in services/grafana.ts has no `description` field at all, though\n * `CreateFolderRequest`/`UpdateFolderRequest` both accept one). Grafana's classic folder GET\n * never returns it, not even as an is-it-set flag the way `DataSource.secureJsonFields` reports\n * for a datasource's secure fields. So `description` is sent on every create/update that\n * declares it but is NEVER part of `matches` — this resource cannot detect drift in a value it\n * is never shown, the same treatment `datasource.ts` gives `secureJsonDataRefs`.\n *\n * ⚠️ NESTING (`parentUid`) IS CREATE-ONLY — MEASURED against the same generated types.\n * `CreateFolderRequest.parentUid` exists; `UpdateFolderRequest` has no `parentUid` field at all\n * (`folder_uid`, `description`, `overwrite`, `title`, `version` — reparenting is simply not a\n * thing `PUT /folders/{uid}` can do). A declaration whose `parentUid` no longer matches the live\n * folder therefore REFUSES with `GrafanaFolderReparentError` rather than either silently doing\n * nothing (which would lie about the declaration taking effect) or deleting and recreating the\n * folder under the new parent (which — see the ⛔ below — takes every dashboard and alert rule in\n * it with it). Move a folder by hand in Grafana, then adjust the declaration to match.\n *\n * ⛔ DELETE DEFAULTS TO `retain` — DELETING A FOLDER DELETES ITS DASHBOARDS AND ALERT RULES IN\n * GRAFANA, per `deleteFolder`'s own operation description (\"along with all dashboards (and their\n * alerts) stored in the folder... cannot be reverted... also deletes all the subfolders\"). That\n * is the same class of multi-object cascade `openbao/mount.ts` guards with\n * `defaultRemovalPolicy: 'retain'` (\"disabling a mount destroys every secret under it\") — VERIFIED\n * there against Alchemy's own `Apply.ts` (not re-verified here; same engine, same option). A\n * stack that explicitly wants the cascade opts in with `.pipe(RemovalPolicy.destroy())` on the\n * declared instance; `destroy` below still implements the real DELETE in full either way (S11).\n * `Grafana.Dashboard` does NOT default to retain — deleting one dashboard is the same\n * single-object blast radius `Grafana.Datasource` already accepts without a retain guard, not\n * this family's multi-object cascade.\n *\n * ⛔ A PROVISIONED FOLDER (`managedBy` set — see provisioned.ts) REFUSES EVERY UPDATE AND DESTROY.\n * `matches` still compares structurally either way, so a mismatched declaration against a\n * provisioned folder shows `update` in a plan (never a silent, permanently-hidden noop) and then\n * fails loudly, by design, when reconcile actually tries to write.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\nimport { type GrafanaProvisionedObjectError, refuseIfProvisioned } from './provisioned.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\n\nexport interface FolderProps {\n uid: string;\n title: string;\n /** Write-only — see the file header. Sent on every create/update that declares it; never diffed. */\n description?: string;\n /** Parent folder UID, for nested folders. Create-only — see the file header. */\n parentUid?: string;\n}\n\nexport interface FolderAttributes {\n uid: string;\n id: number;\n title: string;\n parentUid: string;\n /** Non-empty when Grafana reports this folder as externally managed (e.g. provisioning). */\n managedBy: string;\n url: string;\n version: number;\n}\n\nexport interface GrafanaFolder extends Resource<\n 'Grafana.Folder',\n FolderProps,\n FolderAttributes,\n never\n> {}\n\nexport const GrafanaFolder = Resource<GrafanaFolder>('Grafana.Folder', {\n defaultRemovalPolicy: 'retain',\n});\n\n/** A declared `parentUid` disagrees with the live folder's — `updateFolder` cannot reparent. */\nexport class GrafanaFolderReparentError extends Data.TaggedError('GrafanaFolderReparentError')<{\n readonly message: string;\n}> {}\n\nexport const spec: GrafanaSpec<\n FolderProps,\n grafana.Folder,\n FolderAttributes,\n | grafana.CreateFolderError\n | grafana.GetFolderByUIDError\n | grafana.UpdateFolderError\n | grafana.DeleteFolderError\n | GrafanaProvisionedObjectError\n | GrafanaFolderReparentError\n> = {\n attributes: (live) => ({\n id: live.id ?? 0,\n managedBy: live.managedBy ?? '',\n parentUid: live.parentUid ?? '',\n title: live.title ?? '',\n uid: live.uid ?? '',\n url: live.url ?? '',\n version: live.version ?? 0,\n }),\n create: (props) =>\n grafana.createFolder({\n uid: props.uid,\n title: props.title,\n ...(props.description === undefined ? {} : { description: props.description }),\n ...(props.parentUid === undefined ? {} : { parentUid: props.parentUid }),\n }),\n destroy: (props, live) =>\n Effect.gen(function* () {\n if (live.managedBy) {\n return yield* refuseIfProvisioned('Grafana.Folder', props.uid, live.managedBy);\n }\n yield* grafana.deleteFolder({ folder_uid: props.uid });\n }),\n fetchLive: (props) =>\n grafana\n .getFolderByUID({ folder_uid: props.uid })\n .pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n matches: (attributes, props) =>\n attributes.title === props.title &&\n (props.parentUid === undefined || attributes.parentUid === props.parentUid),\n update: (props, live) =>\n Effect.gen(function* () {\n if (live.managedBy) {\n return yield* refuseIfProvisioned('Grafana.Folder', props.uid, live.managedBy);\n }\n if (props.parentUid !== undefined && props.parentUid !== (live.parentUid ?? undefined)) {\n return yield* Effect.fail(\n new GrafanaFolderReparentError({\n message:\n `Grafana.Folder '${props.uid}' declares parentUid '${props.parentUid}' but is ` +\n `live under '${live.parentUid ?? '(root)'}'. PUT /folders/{uid} cannot reparent a ` +\n `folder — move it by hand in Grafana, then update the declaration to match.`,\n }),\n );\n }\n // ⚠️ UNLIKE DASHBOARD.TS's 412, THIS HAS NO VERIFIED CONFLICT SIGNAL. `version` is sent\n // optimistically, but the SDK's own doc comment on `UpdateFolderRequest.version` says\n // \"only used by the legacy folder implementation\" — on Grafana's newer unified-storage\n // folder backend it is plausibly ignored outright, meaning two concurrent title/description\n // writes could silently last-write-win with no error, unlike a dashboard save. NOT\n // MEASURED against a live instance either way (no live calls in this PR; flagged by an\n // adversarial review) — sending it is harmless (a no-op field on a backend that ignores it)\n // and correct on one that still honors it, so it stays, but do not read its PRESENCE here\n // as proof this resource detects folder update conflicts the way dashboard.ts does.\n return yield* grafana.updateFolder({\n folder_uid: props.uid,\n title: props.title,\n ...(props.description === undefined ? {} : { description: props.description }),\n ...(live.version === undefined ? {} : { version: live.version }),\n });\n }),\n};\n\nexport const handlers = grafanaHandlers(spec);\n\nexport const GrafanaFolderProvider = () =>\n Provider.effect(GrafanaFolder, Effect.succeed(GrafanaFolder.Provider.of(handlers)));\n",
20
+ "/**\n * `Grafana.Team` — a Grafana team, keyed by NAME.\n *\n * Walked against `@distilled.cloud/grafana` 0.2.1 (`@homeflare/distilled-grafana`): `searchTeams`,\n * `createTeam`, `updateTeam`, `deleteTeam`. Upstream Alchemy ships no Grafana family (S1); distilled\n * ships the SDK, so every call goes through it (S23).\n *\n * ★ NAME IS THE KEY, NOT `uid`. `CreateTeamRequest` takes only `name`/`email` — there is no way to\n * choose a team uid, and Grafana enforces unique team names per org. `fetchLive` therefore runs\n * `GET /teams/search?name=<name>` (an exact-name filter) and keeps only an exact match; adoption of a\n * team created by hand or by a script is a plain observe (S9/S10).\n * ★ `email` is optional and compared only when declared (\"undeclared means don't care\", the kit's\n * convention for optional props).\n * ⛔ A provisioned team (`isProvisioned`, e.g. synced from SCIM/LDAP) is refused for update and delete.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Effect from 'effect/Effect';\nimport { type GrafanaProvisionedObjectError, refuseIfProvisioned } from './provisioned.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\n\nexport interface TeamProps {\n /** Team name — unique per org, and this resource's identity. */\n name: string;\n /** Optional team email; compared only when declared. */\n email?: string;\n}\n\nexport interface TeamAttributes {\n id: number;\n uid: string;\n name: string;\n email: string;\n isProvisioned: boolean;\n}\n\nexport interface GrafanaTeam extends Resource<'Grafana.Team', TeamProps, TeamAttributes, never> {}\n\nexport const GrafanaTeam = Resource<GrafanaTeam>('Grafana.Team');\n\n/** Exact-name lookup. `/teams/search?name=` is already exact in Grafana; the filter keeps that true. */\nexport const findTeamByName = (name: string) =>\n grafana\n .searchTeams({ name, perpage: 100 })\n .pipe(Effect.map((result) => (result.teams ?? []).find((team) => team.name === name)));\n\nexport const spec: GrafanaSpec<\n TeamProps,\n grafana.TeamDTO,\n TeamAttributes,\n | grafana.SearchTeamsError\n | grafana.CreateTeamError\n | grafana.UpdateTeamError\n | grafana.DeleteTeamError\n | GrafanaProvisionedObjectError\n> = {\n attributes: (live) => ({\n email: live.email ?? '',\n id: live.id,\n isProvisioned: live.isProvisioned,\n name: live.name,\n uid: live.uid,\n }),\n create: (props) =>\n grafana.createTeam({\n name: props.name,\n ...(props.email === undefined ? {} : { email: props.email }),\n }),\n destroy: (props, live) =>\n Effect.gen(function* () {\n if (live.isProvisioned) {\n return yield* refuseIfProvisioned(\n 'Grafana.Team',\n props.name,\n 'an external team sync (isProvisioned)',\n );\n }\n yield* grafana.deleteTeam({ team_id: String(live.id) });\n }),\n fetchLive: (props) => findTeamByName(props.name),\n matches: (attributes, props) =>\n attributes.name === props.name &&\n (props.email === undefined || attributes.email === props.email),\n update: (props, live) =>\n Effect.gen(function* () {\n if (live.isProvisioned) {\n return yield* refuseIfProvisioned(\n 'Grafana.Team',\n props.name,\n 'an external team sync (isProvisioned)',\n );\n }\n return yield* grafana.updateTeam({\n team_id: String(live.id),\n name: props.name,\n ...(props.email === undefined ? {} : { email: props.email }),\n });\n }),\n};\n\nexport const handlers = grafanaHandlers(spec);\n\nexport const GrafanaTeamProvider = () =>\n Provider.effect(GrafanaTeam, Effect.succeed(GrafanaTeam.Provider.of(handlers)));\n",
21
+ "/**\n * `Grafana.FolderPermission` — ONE team's DIRECT permission on ONE folder.\n *\n * Walked against `@distilled.cloud/grafana` 0.2.1 (`@homeflare/distilled-grafana`):\n * `getResourcePermissions` (`GET /access-control/folders/{uid}`) and `setResourcePermissionsForTeam`\n * (`POST /access-control/folders/{uid}/teams/{teamId}`).\n *\n * ★ ADDITIVE BY CONSTRUCTION. The per-team endpoint touches only that team's managed entry; the\n * folder's other entries (built-in roles, admin users, other teams, anything inherited from a parent\n * folder) are never read into a write and never changed. The whole-list `setResourcePermissions`\n * would replace them all — deliberately not used.\n * ★ ONLY DIRECT ENTRIES COUNT. An entry inherited from a parent folder (`isInherited`) is not this\n * resource's object: it can't be changed here, so it never satisfies a declaration either.\n * ★ The team is named, not numbered. Team ids differ per instance, so `teamName` is resolved through\n * `findTeamByName` on every read and write; a missing team fails loudly with\n * `GrafanaTeamNotFoundError` (declare the `Grafana.Team` first) instead of folding to \"absent\".\n * ★ delete = set the team's permission to \"\" (Grafana's documented way to remove a managed entry),\n * idempotent: an already-absent entry is a no-op (S11).\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\nimport { findTeamByName } from './team.ts';\n\nexport type FolderPermissionLevel = 'View' | 'Edit' | 'Admin';\n\nexport interface FolderPermissionProps {\n folderUid: string;\n teamName: string;\n permission: FolderPermissionLevel;\n}\n\nexport interface FolderPermissionAttributes {\n folderUid: string;\n teamId: number;\n teamName: string;\n permission: string;\n}\n\nexport interface GrafanaFolderPermission extends Resource<\n 'Grafana.FolderPermission',\n FolderPermissionProps,\n FolderPermissionAttributes,\n never\n> {}\n\nexport const GrafanaFolderPermission = Resource<GrafanaFolderPermission>(\n 'Grafana.FolderPermission',\n);\n\nexport class GrafanaTeamNotFoundError extends Data.TaggedError('GrafanaTeamNotFoundError')<{\n readonly message: string;\n}> {}\n\ninterface LivePermission {\n readonly teamId: number;\n readonly permission: string;\n}\n\nconst resolveTeamId = (teamName: string) =>\n findTeamByName(teamName).pipe(\n Effect.flatMap((team) =>\n team === undefined\n ? Effect.fail(\n new GrafanaTeamNotFoundError({\n message: `Grafana.FolderPermission: team '${teamName}' does not exist. Declare it with Grafana.Team first.`,\n }),\n )\n : Effect.succeed(team.id),\n ),\n );\n\nconst setTeam = (folderUid: string, teamId: number, permission: string) =>\n grafana.setResourcePermissionsForTeam({\n resource: 'folders',\n resourceID: folderUid,\n teamID: teamId,\n permission,\n });\n\nexport const spec: GrafanaSpec<\n FolderPermissionProps,\n LivePermission,\n FolderPermissionAttributes,\n | grafana.SearchTeamsError\n | grafana.GetResourcePermissionsError\n | grafana.SetResourcePermissionsForTeamError\n | GrafanaTeamNotFoundError\n> = {\n attributes: (live, props) => ({\n folderUid: props.folderUid,\n permission: live.permission,\n teamId: live.teamId,\n teamName: props.teamName,\n }),\n create: (props) =>\n resolveTeamId(props.teamName).pipe(\n Effect.flatMap((teamId) => setTeam(props.folderUid, teamId, props.permission)),\n ),\n destroy: (props, live) => setTeam(props.folderUid, live.teamId, ''),\n fetchLive: (props) =>\n Effect.gen(function* () {\n const teamId = yield* resolveTeamId(props.teamName);\n const entries = yield* grafana.getResourcePermissions({\n resource: 'folders',\n resourceID: props.folderUid,\n });\n const direct = (entries ?? []).find(\n (entry) => entry.teamId === teamId && entry.isInherited !== true,\n );\n return direct === undefined\n ? undefined\n : { permission: direct.permission ?? '', teamId: teamId };\n }),\n matches: (attributes, props) => attributes.permission === props.permission,\n update: (props, live) => setTeam(props.folderUid, live.teamId, props.permission),\n};\n\nexport const handlers = grafanaHandlers(spec);\n\nexport const GrafanaFolderPermissionProvider = () =>\n Provider.effect(\n GrafanaFolderPermission,\n Effect.succeed(GrafanaFolderPermission.Provider.of(handlers)),\n );\n",
20
22
  "/**\n * `Grafana.ContactPoint` — one Grafana alerting contact point, keyed by `uid`.\n *\n * ⚠️ NO GET-BY-UID ROUTE EXISTS — MEASURED against the SDK's generated operations (grep across\n * `services/grafana.ts` for `routeGet.*[Cc]ontactpoint`: only `routeGetContactpoints` (list,\n * with an optional `name` filter) and `routeGetContactpointsExport`). Unlike\n * `Grafana.Datasource`/`Grafana.Folder`/`Grafana.Dashboard`, `fetchLive` cannot key its read\n * directly on `uid`. Filtering server-side by `name` is NOT a substitute: `name` is a grouping\n * label a declaration can rename (`uid` is the only field this resource keys on, and Grafana's\n * own doc calls `name` \"used as grouping key in the UI\" — several contact points can share one),\n * so narrowing the GET to the DECLARED name would miss a live object still filed under an OLDER\n * name mid-rename, reporting it absent and attempting a duplicate `create`. `fetchLive` instead\n * lists every contact point (`routeGetContactpoints({})`, no filter) and matches `uid`\n * client-side — the same ambiguity `resource.ts`'s header and netbox's `soleMatch` name, resolved\n * the same way: requiring the one field the API is actually keyed on.\n *\n * ⛔ SECRET SETTINGS NEVER APPEAR AS A LITERAL PROP (S25) — same shape as `Grafana.Datasource`'s\n * `secureJsonDataRefs` (`secret-refs.ts`, shared). Grafana does not use a separate top-level\n * \"secure settings\" field for contact points the way it does for datasources; a secure key (a\n * webhook URL with an embedded token, an API key, …) lives INSIDE `settings` on write, and comes\n * back inside `settings` REDACTED on read — Grafana's own docs for the contact-points EXPORT\n * route say as much explicitly (\"Redacted settings will contain RedactedValue instead\"; the\n * plain, non-export GET this resource calls has no `decrypt` option at all, so it is redacted\n * unconditionally). `secureSettingsRefs` therefore names which keys of `settings` are secret —\n * value resolved from an env var NAME fresh inside `create`/`update`'s own effect (S24), merged\n * into `settings` only at that point, never stored and never diffed (see `matches` below).\n *\n * ⛔ A FOREIGN-PROVENANCE CONTACT POINT REFUSES EVERY UPDATE AND DESTROY — `alerting-provenance.ts`,\n * shared with `Grafana.MessageTemplate`/`Grafana.AlertRuleGroup`/`Grafana.NotificationPolicy`.\n * See that file's header for the full reasoning and citations. `create` is never at risk: it only\n * runs when `fetchLive` already found nothing with this `uid`.\n *\n * ⚠️ `X-Disable-Provenance` IS NEVER SET, BY DESIGN. Every create/update through this resource\n * therefore leaves the contact point with `provenance: \"api\"` (Grafana's own default for an\n * object this API just wrote) — which the docs describe as blocking that same object from being\n * edited in the Grafana UI afterward. That is the intended outcome, not an oversight: an object\n * this family declares is meant to be owned by the declaration, the same \"one owner per resource\"\n * posture `provisioned.ts` establishes for folders/dashboards — handing it back to UI-editability\n * by default would silently create the two-owner situation this whole file exists to prevent.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Effect from 'effect/Effect';\nimport {\n type GrafanaProvisionedObjectError,\n isForeignProvenance,\n refuseIfForeignProvenance,\n} from './alerting-provenance.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\nimport { GrafanaSecretRefUnsetError, resolveSecretRefs } from './secret-refs.ts';\nimport { declaredContentMatches } from './subset-match.ts';\n\nexport { GrafanaSecretRefUnsetError };\n\nexport interface ContactPointProps {\n uid: string;\n name: string;\n /** Grafana integration id — `slack`, `webhook`, `email`, `pagerduty`, `opsgenie`, … */\n type: string;\n /** Non-secret settings — shape depends on `type`. Never put a secret VALUE here — declare it\n * in `secureSettingsRefs` instead; see the file header. */\n settings: Record<string, unknown>;\n /** Secure field name (e.g. `url`, `token`, `password`) -> env var NAME holding its value. */\n secureSettingsRefs?: Record<string, string>;\n disableResolveMessage?: boolean;\n}\n\nexport interface ContactPointAttributes {\n uid: string;\n name: string;\n type: string;\n /** As Grafana returns it — any secure key is a redaction placeholder, never the real value. */\n settings: Record<string, unknown>;\n disableResolveMessage: boolean;\n /** `\"\"`/`\"api\"` (this family may write); anything else, INCLUDING `undefined` (Grafana didn't\n * report the field), refuses — see alerting-provenance.ts's \"fails open\" note. */\n provenance: string | undefined;\n}\n\nexport interface GrafanaContactPoint extends Resource<\n 'Grafana.ContactPoint',\n ContactPointProps,\n ContactPointAttributes,\n never\n> {}\n\nexport const GrafanaContactPoint = Resource<GrafanaContactPoint>('Grafana.ContactPoint');\n\n/** `settings` minus every key `secureSettingsRefs` names — the only part `matches` ever compares\n * (a secure key's live value is always a redaction placeholder, never comparable). */\nconst nonSecretSettings = (props: ContactPointProps): Record<string, unknown> => {\n const refs = props.secureSettingsRefs;\n if (refs === undefined) return props.settings;\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props.settings)) {\n if (!(key in refs)) out[key] = value;\n }\n return out;\n};\n\nconst resolveSettings = (props: ContactPointProps) =>\n Effect.map(\n resolveSecretRefs(props.secureSettingsRefs, (field) => `settings.${field}`),\n (secrets) => (secrets === undefined ? props.settings : { ...props.settings, ...secrets }),\n );\n\nexport const spec: GrafanaSpec<\n ContactPointProps,\n grafana.EmbeddedContactPoint,\n ContactPointAttributes,\n | grafana.RouteGetContactpointsError\n | grafana.RoutePostContactpointsError\n | grafana.RoutePutContactpointError\n | grafana.RouteDeleteContactpointsError\n | GrafanaProvisionedObjectError\n | GrafanaSecretRefUnsetError\n> = {\n attributes: (live) => ({\n disableResolveMessage: live.disableResolveMessage ?? false,\n name: live.name ?? '',\n // ⛔ NEVER `?? ''` — an absent field must stay distinguishable from an explicit `\"\"`\n // (ProvenanceNone); see alerting-provenance.ts's \"fails open\" note.\n provenance: live.provenance,\n settings: (live.settings ?? {}) as Record<string, unknown>,\n type: live.type,\n uid: live.uid ?? '',\n }),\n create: (props) =>\n Effect.flatMap(resolveSettings(props), (settings) =>\n grafana.routePostContactpoints({\n name: props.name,\n settings,\n type: props.type,\n uid: props.uid,\n ...(props.disableResolveMessage === undefined\n ? {}\n : { disableResolveMessage: props.disableResolveMessage }),\n }),\n ),\n destroy: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance('Grafana.ContactPoint', props.uid, live.provenance);\n }\n yield* grafana.routeDeleteContactpoints({ UID: props.uid });\n }),\n fetchLive: (props) =>\n grafana\n .routeGetContactpoints({})\n .pipe(Effect.map((points) => points.find((point) => point.uid === props.uid))),\n matches: (attributes, props) =>\n attributes.name === props.name &&\n attributes.type === props.type &&\n attributes.disableResolveMessage === (props.disableResolveMessage ?? false) &&\n declaredContentMatches(nonSecretSettings(props), attributes.settings),\n update: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance('Grafana.ContactPoint', props.uid, live.provenance);\n }\n const settings = yield* resolveSettings(props);\n yield* grafana.routePutContactpoint({\n UID: props.uid,\n name: props.name,\n settings,\n type: props.type,\n uid: props.uid,\n ...(props.disableResolveMessage === undefined\n ? {}\n : { disableResolveMessage: props.disableResolveMessage }),\n });\n }),\n};\n\nexport const handlers = grafanaHandlers(spec);\n\nexport const GrafanaContactPointProvider = () =>\n Provider.effect(GrafanaContactPoint, Effect.succeed(GrafanaContactPoint.Provider.of(handlers)));\n",
21
23
  "/**\n * `Grafana.MessageTemplate` — one Grafana notification-template group, keyed by `name`.\n *\n * ⚠️ CREATE AND UPDATE ARE THE SAME WIRE CALL — MEASURED: `services/grafana.ts` has no\n * `routePostTemplate` at all, only `routePutTemplate` (`PUT /v1/provisioning/templates/{name}`,\n * upsert by name), `routeGetTemplate`/`routeGetTemplates` and `routeDeleteTemplate`. `spec.create`\n * and `spec.update` both call it — kept as two separate functions anyway (rather than omitting\n * `update` and letting them collapse into one) so the shared engine's `diff` reports a content\n * change as `update`, not the `replace` it would show for any resource whose `spec.update` is\n * undefined (`resource.ts`).\n *\n * ⛔ A FOREIGN-PROVENANCE TEMPLATE REFUSES EVERY UPDATE AND DESTROY — `alerting-provenance.ts`,\n * shared with `Grafana.ContactPoint`/`AlertRuleGroup`/`NotificationPolicy`; see that file's\n * header. `create` is never at risk: it only runs when `fetchLive` already found nothing.\n *\n * ⚠️ `version` IS SENT FOR OPTIMISTIC CONCURRENCY WHEN GRAFANA REPORTS ONE — `RoutePutTemplateRequest.\n * version`'s own doc comment: \"Version of template to use for optimistic concurrency. Leave empty\n * to disable validation.\" Unlike `Grafana.Dashboard`'s 412, no live call confirms what error this\n * produces on a genuine mismatch (no live calls in this PR) — whatever typed error the SDK\n * declares for `routePutTemplate` is left uncaught either way, per the house rule against\n * folding a non-not-found error into absent.\n *\n * ⚠️ `X-Disable-Provenance` IS NEVER SET — same reasoning as `contact-point.ts`'s file header.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Effect from 'effect/Effect';\nimport {\n type GrafanaProvisionedObjectError,\n isForeignProvenance,\n refuseIfForeignProvenance,\n} from './alerting-provenance.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\n\nexport interface MessageTemplateProps {\n name: string;\n /** The Go-template body, e.g. Grafana's own \"Export as JSON/YAML\" template text. */\n template: string;\n}\n\nexport interface MessageTemplateAttributes {\n name: string;\n template: string;\n /** `\"\"`/`\"api\"` (this family may write); anything else, INCLUDING `undefined` (Grafana didn't\n * report the field), refuses — see alerting-provenance.ts's \"fails open\" note. */\n provenance: string | undefined;\n}\n\nexport interface GrafanaMessageTemplate extends Resource<\n 'Grafana.MessageTemplate',\n MessageTemplateProps,\n MessageTemplateAttributes,\n never\n> {}\n\nexport const GrafanaMessageTemplate = Resource<GrafanaMessageTemplate>('Grafana.MessageTemplate');\n\nexport const spec: GrafanaSpec<\n MessageTemplateProps,\n grafana.NotificationTemplate,\n MessageTemplateAttributes,\n | grafana.RouteGetTemplateError\n | grafana.RoutePutTemplateError\n | grafana.RouteDeleteTemplateError\n | GrafanaProvisionedObjectError\n> = {\n attributes: (live) => ({\n name: live.name ?? '',\n // ⛔ NEVER `?? ''` — see alerting-provenance.ts's \"fails open\" note.\n provenance: live.provenance,\n template: live.template ?? '',\n }),\n create: (props) => grafana.routePutTemplate({ name: props.name, template: props.template }),\n destroy: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance(\n 'Grafana.MessageTemplate',\n props.name,\n live.provenance,\n );\n }\n yield* grafana.routeDeleteTemplate({ name: props.name });\n }),\n fetchLive: (props) =>\n grafana\n .routeGetTemplate({ name: props.name })\n .pipe(Effect.catchTag('NotFound', () => Effect.succeed(undefined))),\n matches: (attributes, props) => attributes.template === props.template,\n update: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance(\n 'Grafana.MessageTemplate',\n props.name,\n live.provenance,\n );\n }\n yield* grafana.routePutTemplate({\n name: props.name,\n template: props.template,\n ...(live.version === undefined ? {} : { version: live.version }),\n });\n }),\n};\n\nexport const handlers = grafanaHandlers(spec);\n\nexport const GrafanaMessageTemplateProvider = () =>\n Provider.effect(\n GrafanaMessageTemplate,\n Effect.succeed(GrafanaMessageTemplate.Provider.of(handlers)),\n );\n",
22
24
  "/**\n * `Grafana.MuteTiming` — one Grafana alerting mute timing, keyed by `name` (there is no separate\n * `uid` — `routeGetMuteTiming`/`routePutMuteTiming`/`routeDeleteMuteTiming` are all name-keyed on\n * the wire, and `name` is the field a notification policy's own `mute_time_intervals` references).\n *\n * ★ `provenance`/`version` ARE READ THROUGH A WIDENED TYPE, NOT THE SDK's OWN `MuteTimeInterval` —\n * MEASURED, and a genuinely surprising result worth recording in full. The SDK's generated\n * `MuteTimeInterval` interface (`packages/distilled-grafana/src/services/grafana.ts`) declares\n * only `name`/`time_intervals` — no `provenance`, no `version` — unlike `EmbeddedContactPoint`/\n * `NotificationTemplate`/`ProvisionedAlertRule`/`Route`, which all carry `provenance`. A first\n * pass at this file assumed that meant the data was gone: decoding a raw payload containing both\n * fields through `S.decodeUnknownSync(MuteTimeInterval)` directly DOES strip them. But that is\n * the wrong code path — it is not what `routeGetMuteTiming` itself does. Proven empirically by\n * calling the REAL operation (through `fake-grafana.ts`'s harness, the exact path this file's own\n * `fetchLive` uses) with a response body containing `provenance`/`version`: both come through on\n * the decoded value intact. The mechanism, read from `@distilled.cloud/core@1.0.0-rc.12`'s\n * `protocol-rest.ts`/`protocol-http.ts` (the runtime this SDK's every operation shares): response\n * decoding is `JSON.parse` + `mapKeys` (renames only the field names a schema DOES declare) +\n * `wrapSensitive` (wraps only fields a schema marks sensitive in `Redacted`) — never a strict\n * `Schema.decode`. `protocol-http.ts`'s `mapKeys`, object branch: every response key NOT among a\n * type's declared `props` is copied to the output verbatim in a second pass\n * (`for (const [k, v] of Object.entries(value)) { if (consumed.has(k)) continue; out[k] = v; }`,\n * line ~297-311) — the doc comment on the sibling `wrapSensitive` states the same rule plainly:\n * \"Keys the schema doesn't model pass through verbatim.\" So the TS type is simply narrower than\n * the runtime value; `MuteTimeIntervalWire` below is that same runtime value, typed honestly.\n * This is a real, worth-fixing SDK type-generation gap (tracked in `docs/upstream-conformance.md`,\n * same S22 route as the other named gaps) but NOT a data-loss gap — unlike, say, a field the wire\n * protocol itself never sent, this one is fully recoverable without touching vendored `src/`.\n *\n * The same test proved the outbound direction too: an object with extra keys (`weekdays`, `times`\n * — the real Alertmanager time-interval fields Grafana's OpenAPI's own `TimeInterval` schema\n * apparently fails to model either, for the same reason) passed to `routePutMuteTiming` reaches\n * the wire body unchanged — `mapKeys`'s encode direction is the same verbatim-passthrough rule.\n * `MuteTimingProps.timeIntervals` is therefore typed as the opaque `Record<string, unknown>`\n * shape actually needed to declare a real mute timing (weekdays/times/months/etc.), not the\n * SDK's own too-narrow `TimeInterval`, and cast at the two call sites below.\n *\n * ⚠️ THE EVIDENCE ABOVE IS A HAND-AUTHORED FIXTURE, NOT A CAPTURED REAL RESPONSE — flagged by an\n * adversarial review of this PR. The estate has zero live mute timings to observe (grafana.md's\n * census), so nothing confirms Grafana always includes `provenance` on this route in practice,\n * or that some other SDK/version edge case never drops it. That is exactly why `attributes()`\n * below never coerces a missing `live.provenance` to `''` — see alerting-provenance.ts's \"fails\n * open\" note — an absent field refuses a write rather than being trusted as `ProvenanceNone`.\n *\n * ⛔ A FOREIGN-PROVENANCE MUTE TIMING REFUSES EVERY UPDATE AND DESTROY — `alerting-provenance.ts`,\n * shared with `Grafana.ContactPoint`/`MessageTemplate`/`AlertRuleGroup`/`NotificationPolicy`; see\n * that file's header. `create` is never at risk: it only runs when `fetchLive` already found\n * nothing with this `name`.\n *\n * ⚠️ `version` IS SENT ON DESTROY, NOT ON UPDATE — MEASURED: `RouteDeleteMuteTimingRequest.version`\n * (\"Version of mute timing to use for optimistic concurrency. Leave empty to disable validation\")\n * exists; `RoutePutMuteTimingRequest` has no `version` field at all, so an update has nothing to\n * send for it — a real Grafana API asymmetry between the two write routes, not an omission here.\n *\n * ⚠️ `X-Disable-Provenance` IS NEVER SET — same reasoning as `contact-point.ts`'s file header.\n */\nimport { Resource } from 'alchemy';\nimport * as Provider from 'alchemy/Provider';\nimport * as grafana from '@distilled.cloud/grafana';\nimport * as Effect from 'effect/Effect';\nimport {\n type GrafanaProvisionedObjectError,\n isForeignProvenance,\n refuseIfForeignProvenance,\n} from './alerting-provenance.ts';\nimport { type GrafanaSpec, grafanaHandlers } from './resource.ts';\nimport { declaredContentMatches } from './subset-match.ts';\n\nexport interface MuteTimingProps {\n name: string;\n /** Grafana's Alertmanager-style time-interval entries (`weekdays`/`times`/`months`/…), passed\n * through opaquely — see the file header for why this is not the SDK's own `TimeInterval`. */\n timeIntervals: ReadonlyArray<Record<string, unknown>>;\n}\n\nexport interface MuteTimingAttributes {\n name: string;\n timeIntervals: ReadonlyArray<Record<string, unknown>>;\n /** `\"\"`/`\"api\"` (this family may write); anything else, INCLUDING `undefined` (Grafana didn't\n * report the field, or the widened-type passthrough this file depends on turns out not to hold\n * for some response shape not yet observed), refuses — see alerting-provenance.ts's \"fails\n * open\" note. This is the field where that default matters most: unlike the other resources in\n * this family, `provenance` here is not even in the SDK's declared type. */\n provenance: string | undefined;\n}\n\nexport interface GrafanaMuteTiming extends Resource<\n 'Grafana.MuteTiming',\n MuteTimingProps,\n MuteTimingAttributes,\n never\n> {}\n\nexport const GrafanaMuteTiming = Resource<GrafanaMuteTiming>('Grafana.MuteTiming');\n\n/** The real runtime shape of a `GET`/list response — see the file header's \"measured\" note. */\ntype MuteTimeIntervalWire = grafana.MuteTimeInterval & {\n provenance?: string;\n version?: string;\n};\n\nexport const spec: GrafanaSpec<\n MuteTimingProps,\n MuteTimeIntervalWire,\n MuteTimingAttributes,\n | grafana.RouteGetMuteTimingError\n | grafana.RoutePostMuteTimingError\n | grafana.RoutePutMuteTimingError\n | grafana.RouteDeleteMuteTimingError\n | GrafanaProvisionedObjectError\n> = {\n attributes: (live) => ({\n name: live.name ?? '',\n // ⛔ NEVER `?? ''` — see alerting-provenance.ts's \"fails open\" note, and this file's own\n // Attributes doc comment on why it matters most here.\n provenance: live.provenance,\n timeIntervals: (live.time_intervals ?? []) as unknown as ReadonlyArray<Record<string, unknown>>,\n }),\n create: (props) =>\n grafana.routePostMuteTiming({\n name: props.name,\n time_intervals:\n props.timeIntervals as unknown as grafana.RoutePostMuteTimingRequestTimeIntervalsList,\n }),\n destroy: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance('Grafana.MuteTiming', props.name, live.provenance);\n }\n yield* grafana.routeDeleteMuteTiming({\n name: props.name,\n ...(live.version === undefined ? {} : { version: live.version }),\n });\n }),\n fetchLive: (props) =>\n grafana.routeGetMuteTiming({ name: props.name }).pipe(\n Effect.map((live) => live as MuteTimeIntervalWire),\n Effect.catchTag('NotFound', () => Effect.succeed(undefined)),\n ),\n /** Subset match (subset-match.ts), not plain equality — tolerates a default Grafana might\n * inject into a time-interval entry the declaration never set. */\n matches: (attributes, props) =>\n declaredContentMatches(props.timeIntervals, attributes.timeIntervals),\n update: (props, live) =>\n Effect.gen(function* () {\n if (isForeignProvenance(live.provenance)) {\n return yield* refuseIfForeignProvenance('Grafana.MuteTiming', props.name, live.provenance);\n }\n yield* grafana.routePutMuteTiming({\n name: props.name,\n time_intervals:\n props.timeIntervals as unknown as grafana.RoutePutMuteTimingRequestTimeIntervalsList,\n });\n }),\n};\n\nexport const handlers = grafanaHandlers(spec);\n\nexport const GrafanaMuteTimingProvider = () =>\n Provider.effect(GrafanaMuteTiming, Effect.succeed(GrafanaMuteTiming.Provider.of(handlers)));\n",
23
25
  "/**\n * Grafana credentials for this family — a URL plus a TOKEN REFERENCE (an env var NAME), never a\n * literal secret. Wraps `@distilled.cloud/grafana`'s own `Credentials` context directly (S23 —\n * reuse the SDK's own client rather than inventing a second one); this file only adds the house's\n * lazy, per-instance resolution on top of it.\n *\n * ★ ONE `GRAFANA_TOKEN`/`GRAFANA_URL` PAIR ISN'T ENOUGH FOR THIS HOUSE. Unlike Forgejo (one\n * instance), the estate runs at least two Grafanas — `grafana.homeflare.dev` and\n * `teslamate-grafana` on CT100, which the unit's own comment says has \"Own Access SaaS OIDC\n * client, never grafana.homeflare.dev's\". The SDK's `CredentialsFromEnv` reads one fixed pair\n * of names, so a stack declaring against more than one instance needs a target per instance —\n * `grafanaCredentials(target)` below, parameterized the way `litellm/credentials.ts` and\n * `proxmox/credentials.ts` already are in this kit.\n *\n * ⛔ THE TOKEN NEVER TOUCHES A PROP OR AN ATTRIBUTE (S25). `tokenEnv` is a NAME, resolved from\n * `process.env` fresh inside the credentials effect on every request (S24) — a layer built once\n * still re-reads the environment each time an operation runs, the same laziness\n * `litellm/credentials.ts` and the SDK's own `forgejo`/`netbox` `CredentialsFromEnv` have.\n *\n * ⚠️ THE SDK's `Credentials` SERVICE VALUE TYPE IS `Effect.Effect<Config, never, never>` — the\n * error channel is `never` (credentials.d.ts). A missing env var can only surface as a defect\n * here, via `Effect.orDie`, the same trade-off `forgejo/resource.ts` and `netbox/resource.ts`\n * already accept for their own `CredentialsFromEnv`; it is not a choice this file introduces.\n */\nimport { type Config, Credentials } from '@distilled.cloud/grafana/Credentials';\nimport { ConfigError } from '@distilled.cloud/grafana/Errors';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport * as Redacted from 'effect/Redacted';\n\nexport interface GrafanaTarget {\n /** Instance origin, e.g. `https://tesla.homeflare.dev/dash` — never `/api`; the SDK appends it. */\n readonly baseUrl: string;\n /** Env var NAME holding a Grafana service-account token. Never the value itself. */\n readonly tokenEnv: string;\n /** Selects the org a call applies to, via `X-Grafana-Org-Id`. Omit for the default org. */\n readonly orgId?: number | string;\n}\n\nconst resolve = (target: GrafanaTarget): Effect.Effect<Config, never, never> =>\n Effect.sync(() => process.env[target.tokenEnv]).pipe(\n Effect.flatMap((raw) =>\n raw === undefined || raw.trim() === ''\n ? Effect.fail(\n new ConfigError({\n message:\n `${target.tokenEnv} is not set. Export the Grafana service-account token there ` +\n `— never as an Alchemy prop — before running a stack that declares a resource ` +\n `against ${target.baseUrl}.`,\n }),\n )\n : Effect.succeed({\n apiBaseUrl: target.baseUrl.replace(/\\/+$/, ''),\n token: Redacted.make(raw.trim()),\n ...(target.orgId === undefined ? {} : { orgId: target.orgId }),\n } satisfies Config),\n ),\n Effect.orDie,\n );\n\n/** The lazy, per-instance layer `grafanaProviders(target)` composes by default. */\nexport const grafanaCredentials = (target: GrafanaTarget): Layer.Layer<Credentials> =>\n Layer.succeed(Credentials, resolve(target));\n\nexport type { Credentials };\n",
24
- "/**\n * The Grafana providers for one instance, with its credentials, as one layer for a stack.\n *\n * Layer.mergeAll(grafanaProviders({ baseUrl: '...', tokenEnv: 'GRAFANA_TOKEN' }), …)\n *\n * ★ ONE CALL PER INSTANCE. A stack declaring resources against both `grafana.homeflare.dev` and\n * `teslamate-grafana` composes `grafanaProviders(targetA)` and `grafanaProviders(targetB)` —\n * each resource type's `Resource` constructor is a single global registration, so the SAME\n * `Grafana.Datasource` type serves both; only the credential layer differs per call.\n * ⚠️ `HttpClient` is NOT provided here. It is ambient in every Alchemy runtime, the same as\n * `litellmProviders`/`netboxProviders`-style families in this kit assume; a stack that already\n * deploys anything over HTTP already has one.\n */\nimport * as Layer from 'effect/Layer';\nimport { GrafanaAlertRuleGroupProvider } from './alert-rule-group.ts';\nimport { GrafanaContactPointProvider } from './contact-point.ts';\nimport { type GrafanaTarget, grafanaCredentials } from './credentials.ts';\nimport { GrafanaDashboardProvider } from './dashboard.ts';\nimport { GrafanaDatasourceProvider } from './datasource.ts';\nimport { GrafanaFolderProvider } from './folder.ts';\nimport { GrafanaMessageTemplateProvider } from './message-template.ts';\nimport { GrafanaMuteTimingProvider } from './mute-timing.ts';\nimport { GrafanaNotificationPolicyProvider } from './notification-policy.ts';\n\nexport const grafanaProviders = (target: GrafanaTarget) =>\n Layer.mergeAll(\n GrafanaDatasourceProvider(),\n GrafanaFolderProvider(),\n GrafanaDashboardProvider(),\n GrafanaContactPointProvider(),\n GrafanaMuteTimingProvider(),\n GrafanaMessageTemplateProvider(),\n GrafanaAlertRuleGroupProvider(),\n GrafanaNotificationPolicyProvider(),\n ).pipe(Layer.provide(grafanaCredentials(target)));\n"
26
+ "/**\n * The Grafana providers for one instance, with its credentials, as one layer for a stack.\n *\n * Layer.mergeAll(grafanaProviders({ baseUrl: '...', tokenEnv: 'GRAFANA_TOKEN' }), …)\n *\n * ★ ONE CALL PER INSTANCE. A stack declaring resources against both `grafana.homeflare.dev` and\n * `teslamate-grafana` composes `grafanaProviders(targetA)` and `grafanaProviders(targetB)` —\n * each resource type's `Resource` constructor is a single global registration, so the SAME\n * `Grafana.Datasource` type serves both; only the credential layer differs per call.\n * ⚠️ `HttpClient` is NOT provided here. It is ambient in every Alchemy runtime, the same as\n * `litellmProviders`/`netboxProviders`-style families in this kit assume; a stack that already\n * deploys anything over HTTP already has one.\n */\nimport * as Layer from 'effect/Layer';\nimport { GrafanaAlertRuleGroupProvider } from './alert-rule-group.ts';\nimport { GrafanaContactPointProvider } from './contact-point.ts';\nimport { type GrafanaTarget, grafanaCredentials } from './credentials.ts';\nimport { GrafanaDashboardProvider } from './dashboard.ts';\nimport { GrafanaDatasourceProvider } from './datasource.ts';\nimport { GrafanaFolderProvider } from './folder.ts';\nimport { GrafanaFolderPermissionProvider } from './folder-permission.ts';\nimport { GrafanaTeamProvider } from './team.ts';\nimport { GrafanaMessageTemplateProvider } from './message-template.ts';\nimport { GrafanaMuteTimingProvider } from './mute-timing.ts';\nimport { GrafanaNotificationPolicyProvider } from './notification-policy.ts';\n\nexport const grafanaProviders = (target: GrafanaTarget) =>\n Layer.mergeAll(\n GrafanaDatasourceProvider(),\n GrafanaFolderProvider(),\n GrafanaTeamProvider(),\n GrafanaFolderPermissionProvider(),\n GrafanaDashboardProvider(),\n GrafanaContactPointProvider(),\n GrafanaMuteTimingProvider(),\n GrafanaMessageTemplateProvider(),\n GrafanaAlertRuleGroupProvider(),\n GrafanaNotificationPolicyProvider(),\n ).pipe(Layer.provide(grafanaCredentials(target)));\n"
25
27
  ],
26
- "mappings": "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",
27
- "debugId": "5578DCEDF956037C64756E2164756E21",
28
+ "mappings": "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",
29
+ "debugId": "D033FF5CB01A84D864756E2164756E21",
28
30
  "names": []
29
31
  }
@@ -13,5 +13,5 @@
13
13
  */
14
14
  import * as Layer from 'effect/Layer';
15
15
  import { type GrafanaTarget } from './credentials.ts';
16
- export declare const grafanaProviders: (target: GrafanaTarget) => Layer.Layer<import("alchemy").Provider<import("./alert-rule-group.ts").GrafanaAlertRuleGroup> | import("alchemy").Provider<import("./contact-point.ts").GrafanaContactPoint> | import("alchemy").Provider<import("./dashboard.ts").GrafanaDashboard> | import("alchemy").Provider<import("./datasource.ts").GrafanaDatasource> | import("alchemy").Provider<import("./folder.ts").GrafanaFolder> | import("alchemy").Provider<import("./message-template.ts").GrafanaMessageTemplate> | import("alchemy").Provider<import("./mute-timing.ts").GrafanaMuteTiming> | import("alchemy").Provider<import("./notification-policy.ts").GrafanaNotificationPolicy>, never, import("effect/http/HttpClient").HttpClient>;
16
+ export declare const grafanaProviders: (target: GrafanaTarget) => Layer.Layer<import("alchemy").Provider<import("./alert-rule-group.ts").GrafanaAlertRuleGroup> | import("alchemy").Provider<import("./contact-point.ts").GrafanaContactPoint> | import("alchemy").Provider<import("./dashboard.ts").GrafanaDashboard> | import("alchemy").Provider<import("./datasource.ts").GrafanaDatasource> | import("alchemy").Provider<import("./folder.ts").GrafanaFolder> | import("alchemy").Provider<import("./folder-permission.ts").GrafanaFolderPermission> | import("alchemy").Provider<import("./message-template.ts").GrafanaMessageTemplate> | import("alchemy").Provider<import("./mute-timing.ts").GrafanaMuteTiming> | import("alchemy").Provider<import("./notification-policy.ts").GrafanaNotificationPolicy> | import("alchemy").Provider<import("./team.ts").GrafanaTeam>, never, import("effect/http/HttpClient").HttpClient>;
17
17
  //# sourceMappingURL=providers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/grafana/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,kBAAkB,CAAC;AAQ1E,eAAO,MAAM,gBAAgB,WAAY,aAAa,qrBAUH,CAAC"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/grafana/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,kBAAkB,CAAC;AAU1E,eAAO,MAAM,gBAAgB,WAAY,aAAa,00BAYH,CAAC"}
@@ -6,6 +6,6 @@ export declare class GrafanaProvisionedObjectError extends GrafanaProvisionedObj
6
6
  readonly message: string;
7
7
  }> {
8
8
  }
9
- export declare const refuseIfProvisioned: (kind: 'Grafana.Folder' | 'Grafana.Dashboard', uid: string, owner: string | undefined) => Effect.Effect<never, GrafanaProvisionedObjectError>;
9
+ export declare const refuseIfProvisioned: (kind: 'Grafana.Folder' | 'Grafana.Dashboard' | 'Grafana.Team', uid: string, owner: string | undefined) => Effect.Effect<never, GrafanaProvisionedObjectError>;
10
10
  export {};
11
11
  //# sourceMappingURL=provisioned.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provisioned.d.ts","sourceRoot":"","sources":["../../src/grafana/provisioned.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;;;;AAExC,qBAAa,6BAA8B,SAAQ,mCAEjD;IACA,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,eAAO,MAAM,mBAAmB,SACxB,gBAAgB,GAAG,mBAAmB,OACvC,MAAM,SACJ,MAAM,GAAG,SAAS,KACxB,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,6BAA6B,CAcpD,CAAC"}
1
+ {"version":3,"file":"provisioned.d.ts","sourceRoot":"","sources":["../../src/grafana/provisioned.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;;;;AAExC,qBAAa,6BAA8B,SAAQ,mCAEjD;IACA,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,eAAO,MAAM,mBAAmB,SACxB,gBAAgB,GAAG,mBAAmB,GAAG,cAAc,OACxD,MAAM,SACJ,MAAM,GAAG,SAAS,KACxB,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,6BAA6B,CAcpD,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `Grafana.Team` — a Grafana team, keyed by NAME.
3
+ *
4
+ * Walked against `@distilled.cloud/grafana` 0.2.1 (`@homeflare/distilled-grafana`): `searchTeams`,
5
+ * `createTeam`, `updateTeam`, `deleteTeam`. Upstream Alchemy ships no Grafana family (S1); distilled
6
+ * ships the SDK, so every call goes through it (S23).
7
+ *
8
+ * ★ NAME IS THE KEY, NOT `uid`. `CreateTeamRequest` takes only `name`/`email` — there is no way to
9
+ * choose a team uid, and Grafana enforces unique team names per org. `fetchLive` therefore runs
10
+ * `GET /teams/search?name=<name>` (an exact-name filter) and keeps only an exact match; adoption of a
11
+ * team created by hand or by a script is a plain observe (S9/S10).
12
+ * ★ `email` is optional and compared only when declared ("undeclared means don't care", the kit's
13
+ * convention for optional props).
14
+ * ⛔ A provisioned team (`isProvisioned`, e.g. synced from SCIM/LDAP) is refused for update and delete.
15
+ */
16
+ import { Resource } from 'alchemy';
17
+ import * as Provider from 'alchemy/Provider';
18
+ import * as grafana from '@distilled.cloud/grafana';
19
+ import * as Effect from 'effect/Effect';
20
+ import { type GrafanaProvisionedObjectError } from './provisioned.ts';
21
+ import { type GrafanaSpec } from './resource.ts';
22
+ export interface TeamProps {
23
+ /** Team name — unique per org, and this resource's identity. */
24
+ name: string;
25
+ /** Optional team email; compared only when declared. */
26
+ email?: string;
27
+ }
28
+ export interface TeamAttributes {
29
+ id: number;
30
+ uid: string;
31
+ name: string;
32
+ email: string;
33
+ isProvisioned: boolean;
34
+ }
35
+ export interface GrafanaTeam extends Resource<'Grafana.Team', TeamProps, TeamAttributes, never> {
36
+ }
37
+ export declare const GrafanaTeam: import("alchemy").ResourceClass<GrafanaTeam>;
38
+ /** Exact-name lookup. `/teams/search?name=` is already exact in Grafana; the filter keeps that true. */
39
+ export declare const findTeamByName: (name: string) => Effect.Effect<grafana.TeamDTO | undefined, grafana.SearchTeamsError, grafana.GrafanaOpContext>;
40
+ export declare const spec: GrafanaSpec<TeamProps, grafana.TeamDTO, TeamAttributes, grafana.SearchTeamsError | grafana.CreateTeamError | grafana.UpdateTeamError | grafana.DeleteTeamError | GrafanaProvisionedObjectError>;
41
+ export declare const handlers: {
42
+ list: () => Effect.Effect<never[], never, never>;
43
+ read: ({ olds }: {
44
+ olds: TeamProps;
45
+ }) => Effect.Effect<TeamAttributes | undefined, grafana.BadGateway | import("@distilled.cloud/caddy").BadRequest | grafana.ConfigError | import("@distilled.cloud/caddy").Conflict | grafana.Conflict | import("@distilled.cloud/caddy").Forbidden | grafana.Forbidden | grafana.GatewayTimeout | GrafanaProvisionedObjectError | import("effect/http/HttpClientError").HttpClientError | grafana.InternalServerError | grafana.Locked | import("@distilled.cloud/caddy").NotFound | grafana.NotFound | grafana.ServiceUnavailable | grafana.TooManyRequests | grafana.Unauthorized | grafana.UnknownGrafanaError | import("@distilled.cloud/caddy").UnprocessableEntity, grafana.GrafanaOpContext>;
46
+ diff: ({ news, output }: {
47
+ news: import("alchemy").Input<TeamProps>;
48
+ output: TeamAttributes | undefined;
49
+ }) => Effect.Effect<{
50
+ readonly action: 'update';
51
+ } | {
52
+ readonly action: 'noop';
53
+ } | {
54
+ readonly action: 'replace';
55
+ } | undefined, grafana.BadGateway | import("@distilled.cloud/caddy").BadRequest | grafana.ConfigError | import("@distilled.cloud/caddy").Conflict | grafana.Conflict | import("@distilled.cloud/caddy").Forbidden | grafana.Forbidden | grafana.GatewayTimeout | GrafanaProvisionedObjectError | import("effect/http/HttpClientError").HttpClientError | grafana.InternalServerError | grafana.Locked | import("@distilled.cloud/caddy").NotFound | grafana.NotFound | grafana.ServiceUnavailable | grafana.TooManyRequests | grafana.Unauthorized | grafana.UnknownGrafanaError | import("@distilled.cloud/caddy").UnprocessableEntity, grafana.GrafanaOpContext>;
56
+ reconcile: ({ news }: {
57
+ news: TeamProps;
58
+ }) => Effect.Effect<TeamAttributes, grafana.BadGateway | import("@distilled.cloud/caddy").BadRequest | grafana.ConfigError | import("@distilled.cloud/caddy").Conflict | grafana.Conflict | import("@distilled.cloud/caddy").Forbidden | grafana.Forbidden | grafana.GatewayTimeout | GrafanaProvisionedObjectError | import("effect/http/HttpClientError").HttpClientError | grafana.InternalServerError | grafana.Locked | import("@distilled.cloud/caddy").NotFound | grafana.NotFound | grafana.ServiceUnavailable | grafana.TooManyRequests | grafana.Unauthorized | grafana.UnknownGrafanaError | import("@distilled.cloud/caddy").UnprocessableEntity, grafana.GrafanaOpContext>;
59
+ delete: ({ olds }: {
60
+ olds: TeamProps;
61
+ }) => Effect.Effect<void, grafana.BadGateway | import("@distilled.cloud/caddy").BadRequest | grafana.ConfigError | import("@distilled.cloud/caddy").Conflict | grafana.Conflict | import("@distilled.cloud/caddy").Forbidden | grafana.Forbidden | grafana.GatewayTimeout | GrafanaProvisionedObjectError | import("effect/http/HttpClientError").HttpClientError | grafana.InternalServerError | grafana.Locked | import("@distilled.cloud/caddy").NotFound | grafana.NotFound | grafana.ServiceUnavailable | grafana.TooManyRequests | grafana.Unauthorized | grafana.UnknownGrafanaError | import("@distilled.cloud/caddy").UnprocessableEntity, grafana.GrafanaOpContext>;
62
+ };
63
+ export declare const GrafanaTeamProvider: () => import("effect/Layer").Layer<Provider.Provider<GrafanaTeam>, never, grafana.GrafanaOpContext>;
64
+ //# sourceMappingURL=team.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team.d.ts","sourceRoot":"","sources":["../../src/grafana/team.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,6BAA6B,EAAuB,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAE,KAAK,WAAW,EAAmB,MAAM,eAAe,CAAC;AAElE,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC;CAAG;AAElG,eAAO,MAAM,WAAW,8CAAwC,CAAC;AAEjE,wGAAwG;AACxG,eAAO,MAAM,cAAc,SAAU,MAAM,mGAG+C,CAAC;AAE3F,eAAO,MAAM,IAAI,EAAE,WAAW,CAC5B,SAAS,EACT,OAAO,CAAC,OAAO,EACf,cAAc,EACZ,OAAO,CAAC,gBAAgB,GACxB,OAAO,CAAC,eAAe,GACvB,OAAO,CAAC,eAAe,GACvB,OAAO,CAAC,eAAe,GACvB,6BAA6B,CA4ChC,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;CAAwB,CAAC;AAE9C,eAAO,MAAM,mBAAmB,qGACiD,CAAC"}
@@ -0,0 +1,39 @@
1
+ /** Same shape as container-form.ts's `UnitLine` — structural, so this module imports nothing back. */
2
+ export type EnvironmentLine = readonly [key: string, value: string];
3
+ declare const QuadletEnvironmentValueError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
4
+ readonly _tag: "QuadletEnvironmentValueError";
5
+ } & Readonly<A>;
6
+ /**
7
+ * ⛔ CARRIES THE KEY AND THE RULE, NEVER THE VALUE — an error is logged, retried and pasted into a
8
+ * PR, and a newline-containing value may be arbitrarily large or semi-secret; the key name (which
9
+ * `secretLikeEnvironment` already names in its own messages) is enough to locate the prop.
10
+ */
11
+ export declare class QuadletEnvironmentValueError extends QuadletEnvironmentValueError_base<{
12
+ readonly key: string;
13
+ }> {
14
+ get message(): string;
15
+ }
16
+ /**
17
+ * `Environment="KEY=value"` — the whole assignment double-quoted, with `\`, `"`, `%` and `$`
18
+ * escaped (in that order, over the joined `KEY=value`), so the wrapping quotes this function adds
19
+ * can never be confused with quotes the value contained, every `%` reaches systemd's specifier
20
+ * expansion as the documented `%%` literal instead of an unknown `%x` that invalidates the unit,
21
+ * and every `$` reaches it as `$$` — the documented literal-dollar escape (systemd.service(5)
22
+ * §Command lines) — instead of a `${FOO}` systemd would erase and replace with a variable of ITS
23
+ * choosing, or a `$$` it would fold and halve.
24
+ */
25
+ export declare const quoteEnvironmentValue: (key: string, value: string) => string;
26
+ /**
27
+ * The sorted, quoted `Environment=` lines of a `[Container]` section — spliced by container-form.ts
28
+ * between `EnvironmentFile=` and `Volume=`, exactly where the unquoted renderer emitted them, so
29
+ * the render ORDER does not change (only the bytes of the Environment lines themselves do).
30
+ */
31
+ export declare const environmentLines: (environment: Readonly<Record<string, string>>) => readonly EnvironmentLine[];
32
+ /**
33
+ * The newline refusal as problem STRINGS (containerProblems' currency), so one plan still shows the
34
+ * whole list instead of aborting on the first newline — the typed error above stays the contract
35
+ * for anyone rendering directly.
36
+ */
37
+ export declare const environmentValueProblems: (environment: Readonly<Record<string, string>>) => string[];
38
+ export {};
39
+ //# sourceMappingURL=container-env-quote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-env-quote.d.ts","sourceRoot":"","sources":["../../src/linux/container-env-quote.ts"],"names":[],"mappings":"AA6CA,sGAAsG;AACtG,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;;;;AAQpE;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,kCAAiD;IACjG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;IACA,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,QAAS,MAAM,SAAS,MAAM,KAAG,MAYlE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,gBACd,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAC5C,SAAS,eAAe,EAMoE,CAAC;AAEhG;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,gBACtB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAC5C,MAAM,EAaR,CAAC"}