@domesystems/templates 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -150
- package/bin/dome-templates.mjs +1 -1
- package/package.json +5 -5
- package/src/cli.mjs +219 -26
- package/src/runtime.mjs +2 -2
- package/src/template-files.mjs +72 -0
- package/ai-agent-for-documentation/.env.example +0 -12
- package/ai-agent-for-documentation/app/agent.yaml +0 -31
- package/ai-agent-for-documentation/app/help.md +0 -19
- package/ai-agent-for-documentation/app/instructions.md +0 -21
- package/ai-agent-for-documentation/docker-compose.yml +0 -18
- package/ai-agent-for-documentation/dome.tf +0 -146
- package/ai-agent-for-documentation/rules/answerer.cedar +0 -35
- package/ai-agent-for-documentation/template.yaml +0 -130
- package/ai-agent-for-documentation/verification.json +0 -7
- package/ai-agent-for-notion/.env.example +0 -19
- package/ai-agent-for-notion/app/agent.yaml +0 -32
- package/ai-agent-for-notion/app/help.md +0 -14
- package/ai-agent-for-notion/app/instructions.md +0 -16
- package/ai-agent-for-notion/docker-compose.yml +0 -18
- package/ai-agent-for-notion/dome.tf +0 -163
- package/ai-agent-for-notion/guards/redact-ssn-from-pages.json +0 -22
- package/ai-agent-for-notion/rules/answerer.cedar +0 -29
- package/ai-agent-for-notion/template.yaml +0 -142
- package/ai-agent-for-notion/verification.json +0 -7
- package/ai-agent-for-release-notes/.env.example +0 -15
- package/ai-agent-for-release-notes/app/agent.yaml +0 -36
- package/ai-agent-for-release-notes/app/help.md +0 -20
- package/ai-agent-for-release-notes/app/instructions.md +0 -19
- package/ai-agent-for-release-notes/docker-compose.yml +0 -18
- package/ai-agent-for-release-notes/dome.tf +0 -165
- package/ai-agent-for-release-notes/guards/block-leaked-keys.json +0 -38
- package/ai-agent-for-release-notes/rules/release-notes.cedar +0 -49
- package/ai-agent-for-release-notes/template.yaml +0 -155
|
@@ -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,142 +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
|
-
agent:
|
|
119
|
-
prompt: app/instructions.md
|
|
120
|
-
help: app/help.md
|
|
121
|
-
model: claude-sonnet-5
|
|
122
|
-
max_tokens: 2048
|
|
123
|
-
skills:
|
|
124
|
-
- name: answer-from-notion
|
|
125
|
-
description: Search the workspace, read the most relevant pages, answer from them.
|
|
126
|
-
tools:
|
|
127
|
-
- notion/notion-search
|
|
128
|
-
- notion/notion-fetch
|
|
129
|
-
- notion/notion-create-pages
|
|
130
|
-
invoker:
|
|
131
|
-
kind: chat
|
|
132
|
-
options:
|
|
133
|
-
# alice is permitted, bob is refused. Same question, different answer,
|
|
134
|
-
# because of who is asking rather than what was asked.
|
|
135
|
-
identity:
|
|
136
|
-
mode: oidc-stub
|
|
137
|
-
personas:
|
|
138
|
-
- id: alice
|
|
139
|
-
- id: bob
|
|
140
|
-
model:
|
|
141
|
-
provider: anthropic
|
|
142
|
-
model: claude-sonnet-5
|
|
@@ -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
|
|
@@ -1,165 +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 "github_token" {
|
|
9
|
-
type = string
|
|
10
|
-
sensitive = true
|
|
11
|
-
}
|
|
12
|
-
variable "anthropic_api_key" {
|
|
13
|
-
type = string
|
|
14
|
-
sensitive = true
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
resource "dome_gateway" "release" {
|
|
18
|
-
workspace_id = var.workspace_id
|
|
19
|
-
name = "release"
|
|
20
|
-
description = "Read-only GitHub surface for the release-notes job"
|
|
21
|
-
is_default = true
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
resource "dome_mcp_connection" "github" {
|
|
25
|
-
workspace_id = var.workspace_id
|
|
26
|
-
name = "github"
|
|
27
|
-
protocol = "streamable-http"
|
|
28
|
-
url = "https://api.githubcopilot.com/mcp/"
|
|
29
|
-
auth_method = "api-key"
|
|
30
|
-
credential_type = "shared"
|
|
31
|
-
secret_values = { Authorization = var.github_token }
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
resource "dome_llm_connection" "sonnet" {
|
|
35
|
-
workspace_id = var.workspace_id
|
|
36
|
-
name = "sonnet"
|
|
37
|
-
provider_id = "anthropic"
|
|
38
|
-
provider_config = jsonencode({ model = "claude-sonnet-5" })
|
|
39
|
-
auth_method = "api-key"
|
|
40
|
-
credential_type = "shared"
|
|
41
|
-
secret_values = { Authorization = var.anthropic_api_key }
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
resource "dome_llm_pool" "release" {
|
|
45
|
-
workspace_id = var.workspace_id
|
|
46
|
-
name = "release-pool"
|
|
47
|
-
is_default = true
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
resource "dome_llm_pool_member" "sonnet" {
|
|
51
|
-
workspace_id = var.workspace_id
|
|
52
|
-
pool = dome_llm_pool.release.name
|
|
53
|
-
llm_connection = dome_llm_connection.sonnet.name
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
resource "dome_gateway_llm_pool" "release" {
|
|
57
|
-
workspace_id = var.workspace_id
|
|
58
|
-
gateway = dome_gateway.release.name
|
|
59
|
-
llm_pool = dome_llm_pool.release.name
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
resource "dome_gateway_tool" "list_pull_requests" {
|
|
63
|
-
workspace_id = var.workspace_id
|
|
64
|
-
gateway = dome_gateway.release.name
|
|
65
|
-
mcp_connection = dome_mcp_connection.github.name
|
|
66
|
-
tool = "list_pull_requests"
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
resource "dome_gateway_tool" "pull_request_read" {
|
|
70
|
-
workspace_id = var.workspace_id
|
|
71
|
-
gateway = dome_gateway.release.name
|
|
72
|
-
mcp_connection = dome_mcp_connection.github.name
|
|
73
|
-
tool = "pull_request_read"
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
resource "dome_gateway_tool" "list_commits" {
|
|
77
|
-
workspace_id = var.workspace_id
|
|
78
|
-
gateway = dome_gateway.release.name
|
|
79
|
-
mcp_connection = dome_mcp_connection.github.name
|
|
80
|
-
tool = "list_commits"
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
resource "dome_gateway_tool" "create_issue" {
|
|
84
|
-
workspace_id = var.workspace_id
|
|
85
|
-
gateway = dome_gateway.release.name
|
|
86
|
-
mcp_connection = dome_mcp_connection.github.name
|
|
87
|
-
tool = "create_issue"
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
resource "dome_agent" "release_notes_writer" {
|
|
91
|
-
workspace_id = var.workspace_id
|
|
92
|
-
name = "release-notes-writer"
|
|
93
|
-
allowed_gateways = [dome_gateway.release.name]
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
resource "dome_agent_rules_bundle" "release_notes_writer" {
|
|
97
|
-
workspace_id = var.workspace_id
|
|
98
|
-
agent = dome_agent.release_notes_writer.name
|
|
99
|
-
files = {
|
|
100
|
-
"release-notes.cedar" = <<-EOT
|
|
101
|
-
permit ( principal, action == Dome::Action::"mcp:discover", resource );
|
|
102
|
-
permit ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"github/list_pull_requests" );
|
|
103
|
-
permit ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"github/pull_request_read" );
|
|
104
|
-
permit ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"github/list_commits" );
|
|
105
|
-
forbid ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"github/create_issue" );
|
|
106
|
-
forbid ( principal, action == Dome::Action::"mcp:call", resource == Dome::MCPTool::"github/pull_request_read" ) when { resource.arguments.method == "get_diff" };
|
|
107
|
-
EOT
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
resource "dome_filter" "block_leaked_keys" {
|
|
112
|
-
workspace_id = var.workspace_id
|
|
113
|
-
name = "block-leaked-keys"
|
|
114
|
-
description = "Withhold a tool result carrying a private key"
|
|
115
|
-
config = jsonencode({
|
|
116
|
-
json = { components = [{ fieldActions = [{ matcher = { path = "**.text", contentMatchers = [
|
|
117
|
-
{ substring = { value = "BEGIN RSA PRIVATE KEY" } },
|
|
118
|
-
{ substring = { value = "BEGIN OPENSSH PRIVATE KEY" } },
|
|
119
|
-
{ substring = { value = "BEGIN PRIVATE KEY" } },
|
|
120
|
-
{ substring = { value = "BEGIN EC PRIVATE KEY" } },
|
|
121
|
-
] }, action = "FILTER_ACTION_BLOCK" }] }] }
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
resource "dome_mcp_connection_filters" "github_responses" {
|
|
126
|
-
workspace_id = var.workspace_id
|
|
127
|
-
mcp_connection = dome_mcp_connection.github.name
|
|
128
|
-
direction = "response"
|
|
129
|
-
filters = [dome_filter.block_leaked_keys.name]
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
resource "dome_quota" "agent_daily_spend" {
|
|
133
|
-
workspace_id = var.workspace_id
|
|
134
|
-
dimension = "llm"
|
|
135
|
-
unit = "dome_usd"
|
|
136
|
-
subject_type = "agent"
|
|
137
|
-
subject = dome_agent.release_notes_writer.name
|
|
138
|
-
scope = "total"
|
|
139
|
-
window = "daily"
|
|
140
|
-
limit_amount = 2000000
|
|
141
|
-
name = "release-notes-writer daily spend"
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
resource "dome_quota" "github_calls" {
|
|
145
|
-
workspace_id = var.workspace_id
|
|
146
|
-
dimension = "tool"
|
|
147
|
-
unit = "calls"
|
|
148
|
-
subject_type = "tool_connection"
|
|
149
|
-
subject = dome_mcp_connection.github.name
|
|
150
|
-
scope = "total"
|
|
151
|
-
window = "daily"
|
|
152
|
-
limit_amount = 1000
|
|
153
|
-
name = "github calls per day"
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
resource "dome_agent_key" "runtime" {
|
|
157
|
-
workspace_id = var.workspace_id
|
|
158
|
-
agent = dome_agent.release_notes_writer.name
|
|
159
|
-
name = "runtime"
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
output "release_notes_writer_token" {
|
|
163
|
-
value = dome_agent_key.runtime.token
|
|
164
|
-
sensitive = true
|
|
165
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"json": {
|
|
3
|
-
"components": [
|
|
4
|
-
{
|
|
5
|
-
"fieldActions": [
|
|
6
|
-
{
|
|
7
|
-
"matcher": {
|
|
8
|
-
"path": "**.text",
|
|
9
|
-
"contentMatchers": [
|
|
10
|
-
{
|
|
11
|
-
"substring": {
|
|
12
|
-
"value": "BEGIN RSA PRIVATE KEY"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"substring": {
|
|
17
|
-
"value": "BEGIN OPENSSH PRIVATE KEY"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"substring": {
|
|
22
|
-
"value": "BEGIN PRIVATE KEY"
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"substring": {
|
|
27
|
-
"value": "BEGIN EC PRIVATE KEY"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
},
|
|
32
|
-
"action": "FILTER_ACTION_BLOCK"
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
}
|