postgres implements the store seat's verbs under the seat's name, and its claim says so (hq ADR 0160)
The store's databases and query are registered under mesh-store, so the runtime serves them on the seat's subjects wherever postgres holds the seat and never lists them as postgres's own; the claim names them, so the mesh can judge the holder without postgres listing the seat's verbs among its tools. Scoped to what the store enables: creating a database stays postgres's tool.
This commit is contained in:
@@ -10,7 +10,11 @@
|
||||
"claims": [
|
||||
{
|
||||
"name": "mesh-store",
|
||||
"scope": "mesh"
|
||||
"scope": "mesh",
|
||||
"serves": [
|
||||
"databases",
|
||||
"query"
|
||||
]
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
@@ -133,11 +137,5 @@
|
||||
"from": "Dockerfile"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tools": [
|
||||
"databases",
|
||||
"query",
|
||||
"postgres_list_databases",
|
||||
"postgres_query"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,32 +8,6 @@ import { PostgresClient } from "../client.js";
|
||||
|
||||
export function getPostgresTools(postgres: PostgresClient): ToolDefinition[] {
|
||||
return [
|
||||
// The store seat's verbs (novox/hq ADR 0159), served by this module wherever it holds the seat:
|
||||
// named as the seat names them, so the runtime finds them by name, and answering with the same
|
||||
// calls as this module's own tools below. A holder that is not the store serves nothing here;
|
||||
// the bus admits the seat's subjects only to the holder.
|
||||
{
|
||||
name: "databases",
|
||||
description: "The store seat's verb: every database the store holds, with its on-disk size.",
|
||||
input: {},
|
||||
run: async () => ({ databases: await postgres.listDatabases() }),
|
||||
},
|
||||
{
|
||||
name: "query",
|
||||
description: "The store seat's verb: one read-only statement against one database the store holds.",
|
||||
input: {
|
||||
database: { type: "string", description: "the database to query" },
|
||||
sql: { type: "string", description: "the SELECT (or other read-only) statement" },
|
||||
},
|
||||
run: async (args) => {
|
||||
const database = String(args.database ?? "");
|
||||
const sql = String(args.sql ?? "");
|
||||
if (!database) throw new Error("query: database is required");
|
||||
if (!sql) throw new Error("query: sql is required");
|
||||
const result = await postgres.readOnlyQuery(database, sql);
|
||||
return { database, command: result.command, rows: result.rows };
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "postgres_list_databases",
|
||||
description: "List the databases on the postgres server, with their on-disk size.",
|
||||
@@ -59,6 +33,37 @@ export function getPostgresTools(postgres: PostgresClient): ToolDefinition[] {
|
||||
];
|
||||
}
|
||||
|
||||
// The store seat's verbs (novox/hq ADR 0159, 0160): the role's, not postgres's. Registered under the
|
||||
// seat's name, so the runtime serves them on the seat's subjects wherever this module holds the
|
||||
// seat and never lists them as postgres's own; scoped to what the store enables — asking what it
|
||||
// holds and reading from it — so creating a database is postgres's tool and not the store's.
|
||||
export function getStoreVerbs(postgres: PostgresClient): ToolDefinition[] {
|
||||
return [
|
||||
{
|
||||
name: "databases",
|
||||
description: "Every database the store holds, with its on-disk size.",
|
||||
input: {},
|
||||
run: async () => ({ databases: await postgres.listDatabases() }),
|
||||
},
|
||||
{
|
||||
name: "query",
|
||||
description: "One read-only statement against one database the store holds.",
|
||||
input: {
|
||||
database: { type: "string", description: "the database to query" },
|
||||
sql: { type: "string", description: "the SELECT (or other read-only) statement" },
|
||||
},
|
||||
run: async (args) => {
|
||||
const database = String(args.database ?? "");
|
||||
const sql = String(args.sql ?? "");
|
||||
if (!database) throw new Error("query: database is required");
|
||||
if (!sql) throw new Error("query: sql is required");
|
||||
const result = await postgres.readOnlyQuery(database, sql);
|
||||
return { database, command: result.command, rows: result.rows };
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// The tools exist only when the server can be reached from the environment; without it, postgres
|
||||
// contributes none rather than failing the whole tool runtime.
|
||||
registerModuleTools("postgres", (env) => {
|
||||
@@ -68,3 +73,11 @@ registerModuleTools("postgres", (env) => {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
registerModuleTools("mesh-store", (env) => {
|
||||
try {
|
||||
return getStoreVerbs(PostgresClient.fromEnv(env));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user