Files
mesh-catalog/modules/claude-licence-manager/module.json
T
jschoubben 1c03299721 M-2: the manager's manifest asks for its kept data by template
Eight bus-state entries in the typed long form; the old state and the reads of
claude-code.holdings go, and so does the run-once prepare, since nothing writes the
tables again. The database and grant-key stay as the carry-over's read-only source.
The manifest declares its new events, its consumption of holdings-changed, the
operator channel it uses, the verbs it invokes, six settings and its eight tools.

Builds: design 39 bus-and-switch §1, §9, §21, §23, §27, §33, §37-§44, A3, B9, B16

Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
2026-11-11 23:01:43 +01:00

307 lines
7.1 KiB
JSON

{
"module": "claude-licence-manager",
"version": "1",
"slug": "licmgr",
"requires": [
"postgres-database",
"secret",
{
"name": "licences",
"storage": "key-value",
"template": "state",
"options": {
"history": 1
}
},
{
"name": "bindings",
"storage": "key-value",
"template": "state",
"options": {
"history": 8
}
},
{
"name": "leases",
"storage": "key-value",
"template": "state",
"options": {
"history": 1,
"key-ttl": true
}
},
{
"name": "offered",
"storage": "key-value",
"template": "state",
"options": {
"history": 1,
"key-ttl": true
}
},
{
"name": "usage",
"storage": "stream",
"template": "log",
"options": {
"max-age-days": 35,
"max-mib": 256
}
},
{
"name": "audit",
"storage": "stream",
"template": "log",
"options": {
"max-mib": 64
}
},
{
"name": "carried",
"storage": "key-value",
"template": "state",
"options": {
"history": 1
}
},
{
"name": "conditions",
"storage": "key-value",
"template": "state",
"options": {
"history": 1
}
}
],
"contributes": {
"postgres-database": {
"name": "claude_licences",
"readable": [
"audit",
"binding"
]
}
},
"binds": {
"postgres-database": "${dir:state}/database.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret",
"secret": {
"grant-key": "${dir:state}/grant.key"
}
},
"uses": [
"operator-channel"
],
"invokes": [
"seat:operator-channel.tell",
"seat:mesh-vault.licence-put",
"seat:mesh-vault.get"
],
"seats": [
{
"name": "anthropic-licence-manager",
"scope": "mesh",
"serves": [
"licences",
"bindings",
"bind",
"switch",
"release",
"refresh",
"usage",
"adopt",
"current",
"public-key"
]
}
],
"claims": [
{
"name": "anthropic-licence-manager",
"scope": "mesh",
"serves": [
"licences",
"bindings",
"bind",
"switch",
"release",
"refresh",
"usage",
"adopt",
"current",
"public-key"
]
}
],
"emits": [
"licence.adopted",
"licence.refused",
"licence.switched",
"licence.failing",
"usage.read",
"binding.changed",
"holdings.asked"
],
"consumes": [
"claude-code.holdings-changed"
],
"config": {
"cadence_minutes": {
"type": "number",
"description": "How old a licence's grant may grow before it is rotated, in minutes; 0 keeps 240.",
"minimum": 0,
"trusted": true,
"default": 240
},
"floor_minutes": {
"type": "number",
"description": "How little time a grant may have left before it is refreshed in any case, in minutes; 0 keeps 60.",
"minimum": 0,
"trusted": true,
"default": 60
},
"failures_to_notify": {
"type": "number",
"description": "How many refreshes of a licence fail in a row before the operator is told, a count; 0 keeps 3.",
"minimum": 0,
"trusted": true,
"default": 3
},
"cooldown_hours": {
"type": "number",
"description": "How long after telling the operator about a licence nothing more is said about it, in hours; 0 keeps 24.",
"minimum": 0,
"trusted": true,
"default": 24
},
"refresh_warn_days": {
"type": "number",
"description": "How long before a licence's refresh token itself expires the operator is warned, in days; 0 keeps 3.",
"minimum": 0,
"trusted": true,
"default": 3
},
"switch_auto": {
"type": "boolean",
"description": "Whether the manager moves every consumer off a licence whose session or weekly usage reaches switch_at_pct, to the licence with the most room; off, it still raises its no-room and near-limit conditions.",
"trusted": true,
"default": true
},
"switch_at_pct": {
"type": "number",
"description": "The session or weekly usage of a licence, in percent, at which its consumers are moved to the licence with the most room.",
"minimum": 1,
"maximum": 100,
"trusted": true,
"default": 99
},
"room_below_pct": {
"type": "number",
"description": "What both the session and the weekly usage of a licence must be below, in percent, for it to be a target of a switch.",
"minimum": 1,
"maximum": 100,
"trusted": true,
"default": 90
},
"warn_at_pct": {
"type": "number",
"description": "The session or weekly usage of a licence with consumers, in percent, at which it is warned about once.",
"minimum": 1,
"maximum": 100,
"trusted": true,
"default": 90
},
"usage_minutes": {
"type": "number",
"description": "How often each subscription's usage is read, in minutes.",
"minimum": 1,
"maximum": 60,
"trusted": true,
"default": 5
},
"usage_stale_minutes": {
"type": "number",
"description": "How old a subscription's last successful usage reading may grow before its room is not known and it is said, in minutes.",
"minimum": 5,
"maximum": 180,
"trusted": true,
"default": 15
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "database-url",
"type": "file",
"path": "${dir:state}/database.url",
"mode": "0600",
"template": "files/database.url"
},
{
"id": "settings",
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"takes-config": [
"cadence_minutes",
"floor_minutes",
"failures_to_notify",
"cooldown_hours",
"refresh_warn_days",
"switch_auto",
"switch_at_pct",
"room_below_pct",
"warn_at_pct",
"usage_minutes",
"usage_stale_minutes"
],
"merge": "json",
"template": "files/settings.json"
}
],
"tools": [
"licences_switches",
"licences_read_usage",
"licences_switch_now",
"licences_settings",
"licences_kept",
"licences_resync",
"licences_conditions",
"licences_carried"
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/claude-licence-manager",
"binary": "claude-licence-manager",
"loads": [
"claude-licence-manager"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"MESH_LICENCE_STATE": "${dir:state}",
"MESH_LICENCE_KEY_FILE": "${dir:state}/grant.key",
"MESH_LICENCE_SETTINGS": "${dir:state}/settings.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}