@domesystems/templates 0.1.1 → 0.3.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 (36) hide show
  1. package/README.md +16 -158
  2. package/package.json +8 -5
  3. package/src/cli.mjs +46 -232
  4. package/src/manifest.mjs +33 -0
  5. package/src/publish-files.mjs +68 -0
  6. package/src/registry.mjs +100 -0
  7. package/src/runtime.mjs +2 -2
  8. package/src/template-files.mjs +54 -5
  9. package/ai-agent-for-documentation/.env.example +0 -12
  10. package/ai-agent-for-documentation/app/agent.yaml +0 -31
  11. package/ai-agent-for-documentation/app/help.md +0 -19
  12. package/ai-agent-for-documentation/app/instructions.md +0 -21
  13. package/ai-agent-for-documentation/docker-compose.yml +0 -18
  14. package/ai-agent-for-documentation/dome.tf +0 -146
  15. package/ai-agent-for-documentation/rules/answerer.cedar +0 -35
  16. package/ai-agent-for-documentation/template.yaml +0 -131
  17. package/ai-agent-for-documentation/verification.json +0 -7
  18. package/ai-agent-for-notion/.env.example +0 -19
  19. package/ai-agent-for-notion/app/agent.yaml +0 -32
  20. package/ai-agent-for-notion/app/help.md +0 -14
  21. package/ai-agent-for-notion/app/instructions.md +0 -16
  22. package/ai-agent-for-notion/docker-compose.yml +0 -18
  23. package/ai-agent-for-notion/dome.tf +0 -163
  24. package/ai-agent-for-notion/guards/redact-ssn-from-pages.json +0 -22
  25. package/ai-agent-for-notion/rules/answerer.cedar +0 -29
  26. package/ai-agent-for-notion/template.yaml +0 -143
  27. package/ai-agent-for-notion/verification.json +0 -7
  28. package/ai-agent-for-release-notes/.env.example +0 -15
  29. package/ai-agent-for-release-notes/app/agent.yaml +0 -36
  30. package/ai-agent-for-release-notes/app/help.md +0 -20
  31. package/ai-agent-for-release-notes/app/instructions.md +0 -19
  32. package/ai-agent-for-release-notes/docker-compose.yml +0 -18
  33. package/ai-agent-for-release-notes/dome.tf +0 -165
  34. package/ai-agent-for-release-notes/guards/block-leaked-keys.json +0 -38
  35. package/ai-agent-for-release-notes/rules/release-notes.cedar +0 -49
  36. package/ai-agent-for-release-notes/template.yaml +0 -156
@@ -1,14 +0,0 @@
1
- Ask a question in plain language. The agent searches the connected Notion
2
- workspace, reads the pages it finds, and answers from them.
3
-
4
- **Show detail** in the header opens the design: the topology, which tools are
5
- permitted, and the instructions the model was given.
6
-
7
- **Try changing who is asking.** Alice is permitted. Bob is not, and the same
8
- question comes back refused — the difference is the rule, not the wording.
9
-
10
- **Ask it to create a page.** It will try, and the attempt will be blocked. The
11
- connection carries 43 Notion tools; two are permitted.
12
-
13
- Nothing here is the record. Every call, allowed or refused, is in the audit log
14
- in Dome.
@@ -1,16 +0,0 @@
1
- You answer questions using the connected Notion workspace.
2
-
3
- Work like this:
4
-
5
- 1. Search Notion for pages relevant to the question.
6
- 2. Fetch the most promising two or three and read them.
7
- 3. Answer from what you found, and name the pages you used.
8
-
9
- If the workspace does not contain the answer, say so plainly. Do not fill the
10
- gap from general knowledge — a confident answer that is not in the
11
- documentation is worse than no answer, because the reader cannot tell the
12
- difference.
13
-
14
- Use whatever tools you have been given, and do not decline a request on the
15
- assumption that you lack permission. If an action is not allowed, attempting it
16
- is how you and the person asking find that out; report what came back.
@@ -1,18 +0,0 @@
1
- #
2
- # Without DOME_TOKEN this starts in offline mode: the chrome works and the
3
- # allow-list is still enforced, but tools and model are simulated.
4
- services:
5
- app:
6
- # Built and published by dome-systems/template-runtime.
7
- image: ghcr.io/dome-systems/runtime-py-chat:dev
8
- env_file: .env
9
- volumes:
10
- - ./app:/config:ro
11
- ports:
12
- - "3000:3000"
13
- healthcheck:
14
- test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:3000/health', timeout=2)"]
15
- interval: 30s
16
- timeout: 3s
17
- start_period: 10s
18
- retries: 3
@@ -1,163 +0,0 @@
1
- terraform {
2
- required_providers {
3
- dome = { source = "dome-systems/dome", version = ">= 0.1.0" }
4
- }
5
- }
6
-
7
- variable "workspace_id" { type = string }
8
- variable "anthropic_api_key" {
9
- type = string
10
- sensitive = true
11
- }
12
- variable "actas_hmac_secret" {
13
- type = string
14
- sensitive = true
15
- }
16
-
17
- resource "dome_gateway" "knowledge" {
18
- workspace_id = var.workspace_id
19
- name = "knowledge"
20
- description = "Read-only Notion surface for the knowledge answerer"
21
- is_default = true
22
- }
23
-
24
- resource "dome_mcp_connection" "notion" {
25
- workspace_id = var.workspace_id
26
- name = "notion"
27
- protocol = "streamable-http"
28
- url = "https://mcp.notion.com/mcp"
29
- auth_method = "oauth"
30
- credential_type = "shared"
31
- oauth = {
32
- client_origin = "dcr"
33
- registration_url = "https://mcp.notion.com/register"
34
- authorize_url = "https://mcp.notion.com/authorize"
35
- token_url = "https://mcp.notion.com/token"
36
- revoke_url = "https://mcp.notion.com/token"
37
- default_scopes = ["default"]
38
- }
39
- }
40
-
41
- resource "dome_llm_connection" "sonnet" {
42
- workspace_id = var.workspace_id
43
- name = "sonnet"
44
- provider_id = "anthropic"
45
- provider_config = jsonencode({ model = "claude-sonnet-5" })
46
- auth_method = "api-key"
47
- credential_type = "shared"
48
- secret_values = { Authorization = var.anthropic_api_key }
49
- }
50
-
51
- resource "dome_llm_pool" "answerer" {
52
- workspace_id = var.workspace_id
53
- name = "answerer-pool"
54
- is_default = true
55
- }
56
-
57
- resource "dome_llm_pool_member" "sonnet" {
58
- workspace_id = var.workspace_id
59
- pool = dome_llm_pool.answerer.name
60
- llm_connection = dome_llm_connection.sonnet.name
61
- }
62
-
63
- resource "dome_gateway_llm_pool" "answerer" {
64
- workspace_id = var.workspace_id
65
- gateway = dome_gateway.knowledge.name
66
- llm_pool = dome_llm_pool.answerer.name
67
- }
68
-
69
- resource "dome_gateway_tool" "notion_search" {
70
- workspace_id = var.workspace_id
71
- gateway = dome_gateway.knowledge.name
72
- mcp_connection = dome_mcp_connection.notion.name
73
- tool = "notion-search"
74
- }
75
-
76
- resource "dome_gateway_tool" "notion_fetch" {
77
- workspace_id = var.workspace_id
78
- gateway = dome_gateway.knowledge.name
79
- mcp_connection = dome_mcp_connection.notion.name
80
- tool = "notion-fetch"
81
- }
82
-
83
- # This write tool is deliberately reachable so the agent can demonstrate the
84
- # Cedar refusal below.
85
- resource "dome_gateway_tool" "notion_create_pages" {
86
- workspace_id = var.workspace_id
87
- gateway = dome_gateway.knowledge.name
88
- mcp_connection = dome_mcp_connection.notion.name
89
- tool = "notion-create-pages"
90
- }
91
-
92
- resource "dome_agent" "knowledge_answerer" {
93
- workspace_id = var.workspace_id
94
- name = "knowledge-answerer"
95
- allowed_gateways = [dome_gateway.knowledge.name]
96
- act_as = { method = "hmac", required = false }
97
- act_as_hmac_secret = var.actas_hmac_secret
98
- actas_allowed_subjects = ["alice"]
99
- }
100
-
101
- resource "dome_agent_rules_bundle" "knowledge_answerer" {
102
- workspace_id = var.workspace_id
103
- agent = dome_agent.knowledge_answerer.name
104
- files = {
105
- "answerer.cedar" = <<-EOT
106
- permit ( principal, action == Dome::Action::"mcp:discover", resource );
107
- permit ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"notion/notion-search" );
108
- permit ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"notion/notion-fetch" );
109
- forbid ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"notion/notion-create-pages" );
110
- EOT
111
- }
112
- }
113
-
114
- resource "dome_filter" "redact_ssn_from_pages" {
115
- workspace_id = var.workspace_id
116
- name = "redact-ssn-from-pages"
117
- description = "Redact US SSN patterns out of Notion page content"
118
- config = jsonencode({
119
- json = { components = [{ fieldActions = [{ matcher = { path = "**.text", contentMatchers = [{ ssn = {} }] }, action = "FILTER_ACTION_REDACT", redactTarget = "REDACT_TARGET_CONTENT_MATCHES" }] }] }
120
- })
121
- }
122
-
123
- resource "dome_mcp_connection_filters" "notion_responses" {
124
- workspace_id = var.workspace_id
125
- mcp_connection = dome_mcp_connection.notion.name
126
- direction = "response"
127
- filters = [dome_filter.redact_ssn_from_pages.name]
128
- }
129
-
130
- resource "dome_quota" "agent_daily_spend" {
131
- workspace_id = var.workspace_id
132
- dimension = "llm"
133
- unit = "dome_usd"
134
- subject_type = "agent"
135
- subject = dome_agent.knowledge_answerer.name
136
- scope = "total"
137
- window = "daily"
138
- limit_amount = 5000000
139
- name = "knowledge-answerer daily spend"
140
- }
141
-
142
- resource "dome_quota" "caller_daily_spend" {
143
- workspace_id = var.workspace_id
144
- dimension = "llm"
145
- unit = "dome_usd"
146
- subject_type = "model"
147
- subject = dome_llm_connection.sonnet.name
148
- scope = "per_caller"
149
- window = "daily"
150
- limit_amount = 2000000
151
- name = "per-caller model spend"
152
- }
153
-
154
- resource "dome_agent_key" "runtime" {
155
- workspace_id = var.workspace_id
156
- agent = dome_agent.knowledge_answerer.name
157
- name = "runtime"
158
- }
159
-
160
- output "knowledge_answerer_token" {
161
- value = dome_agent_key.runtime.token
162
- sensitive = true
163
- }
@@ -1,22 +0,0 @@
1
- {
2
- "json": {
3
- "components": [
4
- {
5
- "fieldActions": [
6
- {
7
- "matcher": {
8
- "path": "**.text",
9
- "contentMatchers": [
10
- {
11
- "ssn": {}
12
- }
13
- ]
14
- },
15
- "action": "FILTER_ACTION_REDACT",
16
- "redactTarget": "REDACT_TARGET_CONTENT_MATCHES"
17
- }
18
- ]
19
- }
20
- ]
21
- }
22
- }
@@ -1,29 +0,0 @@
1
- // answer-from-knowledge-base — authorization rules
2
- //
3
- // The Notion MCP server carries 43 tools, twenty-odd of which write:
4
- // create-pages, update-page, move-pages, duplicate-page, create-database.
5
- // Two reads are permitted. One write is deliberately reachable and denied,
6
- // so the refusal can be observed rather than merely asserted.
7
-
8
- permit ( principal, action == Dome::Action::"mcp:discover", resource );
9
-
10
- permit (
11
- principal,
12
- action == Dome::Action::"mcp:call",
13
- resource == Dome::MCPTool::"notion/notion-search"
14
- );
15
-
16
- permit (
17
- principal,
18
- action == Dome::Action::"mcp:call",
19
- resource == Dome::MCPTool::"notion/notion-fetch"
20
- );
21
-
22
- // Registering an agent against a gateway auto-generates an Agent Form policy
23
- // permitting any tool whose `gateways` attribute contains that gateway. A
24
- // permit cannot narrow that; only a forbid can. Cedar forbid always wins.
25
- forbid (
26
- principal,
27
- action == Dome::Action::"mcp:call",
28
- resource == Dome::MCPTool::"notion/notion-create-pages"
29
- );
@@ -1,143 +0,0 @@
1
- apiVersion: templates.domesystems.ai/v1
2
- kind: Template
3
-
4
- metadata:
5
- name: answer-from-knowledge-base
6
- slug: ai-agent-for-notion
7
- title: Ask questions across your Notion workspace
8
- target_query: notion ai agent
9
- summary: >-
10
- A chat agent that answers questions from your Notion workspace. The
11
- connection carries 43 tools, twenty-odd of which write. Two are permitted.
12
- Ask it to create a page and it will try — and Dome will refuse, naming the
13
- rule that refused it.
14
- domain: productivity
15
- shape: interactive-assistant
16
- ui: chat
17
- business_pattern: consumes
18
- governance_interest: [read-only, tool-scoped-access, caller-scoped-access]
19
-
20
- # Library-only topology and documentation data. `dome.tf` is the deployable source.
21
- catalog:
22
- gateway:
23
- name: knowledge
24
- description: Read-only Notion surface for the knowledge answerer
25
- default: true
26
-
27
- connections:
28
- - name: notion
29
- protocol: streamable-http
30
- url: https://mcp.notion.com/mcp
31
- # Notion runs two auth systems for one product: the REST API takes
32
- # internal integration tokens, the MCP server takes user-delegated OAuth
33
- # and 403s an `ntn_` token with `restricted_resource`. Dome self-registers
34
- # via DCR and prints a consent URL.
35
- auth:
36
- method: oauth
37
- credential: shared
38
- oauth:
39
- client_origin: dcr
40
- registration_url: https://mcp.notion.com/register
41
- authorize_url: https://mcp.notion.com/authorize
42
- token_url: https://mcp.notion.com/token
43
- revoke_url: https://mcp.notion.com/token
44
- scopes: [default]
45
- permit:
46
- - notion-search
47
- - notion-fetch
48
- # On the gateway on purpose, so the model can see it and try. Cedar
49
- # forbids it, and a forbid beats the auto-generated Agent Form permit.
50
- # Without this there is no denial to observe.
51
- forbid:
52
- - notion-create-pages
53
-
54
- model:
55
- name: sonnet
56
- provider: anthropic
57
- model_id: claude-sonnet-5
58
- secret:
59
- env: ANTHROPIC_API_KEY
60
- variable: anthropic_api_key
61
- label: an Anthropic API key
62
-
63
- pool:
64
- name: answerer-pool
65
- default: true
66
-
67
- agent:
68
- name: knowledge-answerer
69
- # The gateway will not believe an act-as header it cannot verify. OIDC is
70
- # the real answer but `--actas-oidc-url` must be https on a public host,
71
- # so a stub on a laptop cannot issue; hmac is the local path.
72
- act_as:
73
- method: hmac
74
- required: false # reads without a persona still work
75
- secret: ACTAS_HMAC_SECRET
76
- # Alice may be acted as. Bob may not, and is refused at verification —
77
- # before Cedar is consulted at all.
78
- allowed_subjects: [alice]
79
-
80
- rules:
81
- file: rules/answerer.cedar
82
-
83
- guards:
84
- filters:
85
- - name: redact-ssn-from-pages
86
- description: Redact US SSN patterns out of Notion page content
87
- why: >-
88
- A wiki is where people paste things. Cedar decides which pages the
89
- agent may read; it says nothing about what is inside one. This is the
90
- control for the content rather than the access, and it runs before
91
- the agent — not the provider — sees the page.
92
- config: guards/redact-ssn-from-pages.json
93
- bind: { tool: notion, direction: response }
94
-
95
- quotas:
96
- # What the agent may spend in a day, across model and tool traffic.
97
- - subject: agent
98
- agent: knowledge-answerer
99
- unit: dome_usd
100
- limit: 5
101
- window: daily
102
- name: knowledge-answerer daily spend
103
- # And the same cap applied independently to each verified end user, which
104
- # is the quota that pairs with act-as: one caller cannot spend the agent's
105
- # whole day. Without --per-caller, whoever asks first gets it all.
106
- - subject: model
107
- model: sonnet
108
- unit: dome_usd
109
- limit: 2
110
- window: daily
111
- per_caller: true
112
- name: per-caller model spend
113
-
114
- app:
115
- runtime:
116
- pattern: chat
117
- language: python
118
- image_tag: dev
119
- agent:
120
- prompt: app/instructions.md
121
- help: app/help.md
122
- model: claude-sonnet-5
123
- max_tokens: 2048
124
- skills:
125
- - name: answer-from-notion
126
- description: Search the workspace, read the most relevant pages, answer from them.
127
- tools:
128
- - notion/notion-search
129
- - notion/notion-fetch
130
- - notion/notion-create-pages
131
- invoker:
132
- kind: chat
133
- options:
134
- # alice is permitted, bob is refused. Same question, different answer,
135
- # because of who is asking rather than what was asked.
136
- identity:
137
- mode: oidc-stub
138
- personas:
139
- - id: alice
140
- - id: bob
141
- model:
142
- provider: anthropic
143
- model: claude-sonnet-5
@@ -1,7 +0,0 @@
1
- {
2
- "verified": "2026-09-12T19:25:35Z",
3
- "context": "api-domesystems-ai-dome-systems-core-dome-library",
4
- "gateway": "knowledge",
5
- "agent": "knowledge-answerer",
6
- "cli": "1.0.2"
7
- }
@@ -1,15 +0,0 @@
1
- # The container holds exactly one secret.
2
- #
3
- # Tool credentials went into Dome when dome import ran and live behind the gateway.
4
- # The provider key lives with the Broker. Neither is here, and neither should be.
5
-
6
- # Revealed once after import: dome import outputs <job-id>
7
- DOME_TOKEN=
8
-
9
- # The gateway ROOT — not a bare host, and not the /mcp path.
10
- # Copy the "Gateway URL" from the command above. The container derives
11
- # /mcp for tools and /v1/messages for models from it.
12
- DOME_GATEWAY_URL=
13
-
14
- # the repository to draft notes for, as owner/repo — your choice, and the token must reach it
15
- TARGET_REPO=
@@ -1,36 +0,0 @@
1
- name: release-notes-writer
2
- title: Draft release notes from merged pull requests
3
- summary: "A scheduled job that turns merged pull requests into a release-note draft.\
4
- \ It can read one repository's pull\
5
- \ requests and commits. It cannot open an issue, merge, or cut the release \u2014\
6
- \ and it cannot read the source diff, which is the same tool it is allowed to call,\
7
- \ refused on one of its parameters."
8
- shape: scheduled-job
9
- prompt_file: instructions.md
10
- help_file: help.md
11
- starters:
12
- - Draft release notes for pull requests merged into ${TARGET_REPO} in the 14 days
13
- before ${TODAY}.
14
- model: claude-sonnet-5
15
- pool: release-pool
16
- max_tokens: 8192
17
- skills:
18
- - name: draft-release-notes
19
- description: Read merged pull requests in a window and write user-facing notes.
20
- tools:
21
- - github/list_pull_requests
22
- - github/pull_request_read
23
- - github/list_commits
24
- - github/create_issue
25
- invoker:
26
- kind: cron
27
- schedule: 0 9 * * MON
28
- options:
29
- identity:
30
- mode: none
31
- env:
32
- - name: TARGET_REPO
33
- label: "the repository to draft notes for, as owner/repo \u2014 your choice, and\
34
- \ the token must reach it"
35
- forbidden:
36
- - github/create_issue
@@ -1,20 +0,0 @@
1
- Press **Run now** to draft release notes from pull requests merged since the
2
- last release.
3
-
4
- Runs here are manual. The template declares a weekly schedule, which the Dome
5
- agent runtime will act on once it ships — nothing in this container does.
6
-
7
- The result is the draft. On the left, each run is listed with the calls it made
8
- and how long each took — select an earlier run to compare.
9
-
10
- This agent reads one repository's pull requests and commits. It cannot open an
11
- issue, merge, or cut the release — those calls are refused.
12
-
13
- **Watch the diff get refused.** GitHub replaced nine per-pull-request reads with
14
- one `pull_request_read` tool that takes a `method`, so allowing or denying by
15
- tool name would mean all nine or none. This template allows the tool and
16
- refuses one parameter: `method: get_diff` returns the source code, which release
17
- notes are not written from. The run log shows the same tool permitted on one
18
- call and denied on the next, and the rule that decided it.
19
-
20
- The record of what ran is the audit log in Dome, not this page.
@@ -1,19 +0,0 @@
1
- You draft release notes for a software project.
2
-
3
- Each run:
4
-
5
- 1. List pull requests merged into the default branch of the repository named in
6
- your task, in the window it gives you.
7
- 2. Read the ones whose titles or bodies suggest user-visible change. Skip
8
- dependency bumps, CI changes, and internal refactors unless they change
9
- behavior. Where a title is not enough to say what is now different for a
10
- user, look at the pull request in whatever more detail you can get.
11
- 3. Produce notes in three sections — Added, Changed, Fixed. Omit any section
12
- with nothing in it.
13
-
14
- Write for someone who uses the software and does not read the code. One line
15
- per change, in the present tense, describing what is now different for them.
16
- Link the pull request number at the end of each line.
17
-
18
- If nothing user-visible merged in the window, say exactly that. A release note
19
- that pads an empty week with internal churn trains people to stop reading.
@@ -1,18 +0,0 @@
1
- #
2
- # Without DOME_TOKEN this starts in offline mode: the chrome works and the
3
- # allow-list is still enforced, but tools and model are simulated.
4
- services:
5
- app:
6
- # Built and published by dome-systems/template-runtime.
7
- image: ghcr.io/dome-systems/runtime-py-run:dev
8
- env_file: .env
9
- volumes:
10
- - ./app:/config:ro
11
- ports:
12
- - "3000:3000"
13
- healthcheck:
14
- test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:3000/health', timeout=2)"]
15
- interval: 30s
16
- timeout: 3s
17
- start_period: 10s
18
- retries: 3