@elinpf/dsh-ops-access-prometheus 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.i18n.yaml +4 -0
- package/README.md +32 -0
- package/README.zh.md +32 -0
- package/cordis.patch.yml +1 -0
- package/lib/index.d.ts +31 -0
- package/lib/index.js +61 -0
- package/lib/invariant.d.ts +16 -0
- package/lib/invariant.js +25 -0
- package/lib/types.d.ts +20 -0
- package/lib/types.js +9 -0
- package/package.json +60 -0
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
title: "@elinpf/dsh-ops-access-prometheus"
|
|
2
|
+
description:
|
|
3
|
+
zh: "运维模式 Prometheus 凭证 provider — 校验 prometheus 注册表条目(服务器 URL + 可选 bearer token)并展开 token 路径"
|
|
4
|
+
en: "Prometheus credential provider for ops mode — validates prometheus registry entries (server URL + optional bearer token) and expands the token path"
|
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @elinpf/dsh-ops-access-prometheus
|
|
2
|
+
|
|
3
|
+
The Prometheus credential provider for DeepSeek Harness ops mode — validates `prometheus` registry entries (server URL + optional bearer token) and expands the token path.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
One provider per credential kind, per the ops-access three-role split: core owns the registry and the `ctx.opsAccess` service; this package supplies only the prometheus kind — a zod entry schema plus field processing.
|
|
8
|
+
|
|
9
|
+
- **Entry schema**: `{ url, token? }` — `url` is the Prometheus server's base URL (http(s) only). `token` is optional bearer-token CONTENT: the admin UI / `register_access` accept the pasted token, core writes it to a managed file under `~/.dsh-ops/credentials/` and stores the path — the token never sits in the registry.
|
|
10
|
+
- **process**: strips trailing slashes from the URL and expands a leading `~` in the token path.
|
|
11
|
+
- **validateContent**: save-time paste guard — a token must be a single line (it is sent verbatim in the `Authorization` header; an interior newline would fail at request time). Structural only, no connectivity checks.
|
|
12
|
+
- **No capability probe**: the Prometheus HTTP API is read-only by nature (`query`/`query_range`), so there is no ro/rw distinction to verify. `knownLimits` says so and points at pairing with the same cluster's k8s profile.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Provider row of the ops preset's `agent.cordis.yml`:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- id: ops-access-prometheus
|
|
20
|
+
name: '@elinpf/dsh-ops-access-prometheus'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Registration goes through `registerAccessProvider` (deferred `ctx.inject` + effect lifecycle, so HMR unloads it) — never a static `inject` on `opsAccess`, which deadlocks the loader.
|
|
24
|
+
|
|
25
|
+
## Testing
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm run build # tsc → lib/
|
|
29
|
+
npx vitest run # schema, process, paste guard, registration/HMR disposal
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
No server needed: all tests run against the pure provider object and a mock mount.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @elinpf/dsh-ops-access-prometheus
|
|
2
|
+
|
|
3
|
+
运维模式 Prometheus 凭证 provider — 校验 `prometheus` 注册表条目(服务器 URL + 可选 bearer token)并展开 token 路径。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
按 ops-access 三角色拆分,一种凭证一个 provider:core 拥有注册表和 `ctx.opsAccess` 服务;本包只提供 prometheus 这一种 — 一个 zod 条目 schema 加字段处理。
|
|
8
|
+
|
|
9
|
+
- **条目 schema**:`{ url, token? }` — `url` 是 Prometheus 服务器的 base URL(仅 http(s))。`token` 是可选的 bearer-token 内容:管理 UI / `register_access` 接受粘贴的 token,core 将其写入 `~/.dsh-ops/credentials/` 下的受管文件并存路径 — token 本身不进注册表。
|
|
10
|
+
- **process**:剥掉 URL 末尾的斜杠,展开 token 路径开头的 `~`。
|
|
11
|
+
- **validateContent**:保存时的粘贴防护 — token 必须是单行(它会原样进 `Authorization` 头,内部换行会在请求时失败)。只查结构,不做连通性检查。
|
|
12
|
+
- **无能力探测**:Prometheus HTTP API 天然只读(`query`/`query_range`),没有 ro/rw 之分可核验。`knownLimits` 写明这一点,并提示与同集群的 k8s 档案配对使用。
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
ops preset 的 `agent.cordis.yml` 中的 provider 行:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- id: ops-access-prometheus
|
|
20
|
+
name: '@elinpf/dsh-ops-access-prometheus'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
注册走 `registerAccessProvider`(延迟 `ctx.inject` + effect 生命周期,HMR 可卸载)— 绝不静态 `inject` `opsAccess`,那会死锁加载器。
|
|
24
|
+
|
|
25
|
+
## 测试
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm run build # tsc → lib/
|
|
29
|
+
npx vitest run # schema、process、粘贴防护、注册/HMR 卸载
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
无需服务器:全部测试只打纯 provider 对象和 mock 挂载。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ops access provider for Prometheus.
|
|
3
|
+
*
|
|
4
|
+
* Validates `prometheus` registry entries (`{ url, token? }`). The URL is
|
|
5
|
+
* plain connection metadata and may surface in tool output; `token` is a
|
|
6
|
+
* fileField — the admin UI / register_access accept token CONTENT, core
|
|
7
|
+
* writes it to a managed file under ~/.dsh-ops/credentials/ and stores the
|
|
8
|
+
* path, so the token itself never sits in the registry, logs, or model
|
|
9
|
+
* context. The provider expands ~ in the token path for the tool's read.
|
|
10
|
+
*
|
|
11
|
+
* No capability probe: the Prometheus HTTP API is read-only by nature
|
|
12
|
+
* (query/query_range), so there is no ro/rw distinction to verify — both
|
|
13
|
+
* tiers serve the same connection parameters.
|
|
14
|
+
*
|
|
15
|
+
* @module @elinpf/dsh-ops-access-prometheus
|
|
16
|
+
*/
|
|
17
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
18
|
+
import z from '@deepseek-ai/schemastery';
|
|
19
|
+
import { z as zod } from 'zod';
|
|
20
|
+
import type { AccessProvider } from '@elinpf/dsh-ops-access';
|
|
21
|
+
export type { PrometheusEntry } from './types.js';
|
|
22
|
+
export declare const name = "ops-access-prometheus";
|
|
23
|
+
export declare const inject: string[];
|
|
24
|
+
export declare const Config: z<Schemastery.ObjectS<{}>, Schemastery.ObjectT<{}>>;
|
|
25
|
+
/** Zod schema for one prometheus registry entry (excluding name and envelope fields). */
|
|
26
|
+
export declare const entrySchema: zod.ZodObject<{
|
|
27
|
+
url: zod.ZodURL;
|
|
28
|
+
token: zod.ZodOptional<zod.ZodString>;
|
|
29
|
+
}, zod.core.$strip>;
|
|
30
|
+
export declare const provider: AccessProvider;
|
|
31
|
+
export declare function apply(ctx: Context): void;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ops access provider for Prometheus.
|
|
3
|
+
*
|
|
4
|
+
* Validates `prometheus` registry entries (`{ url, token? }`). The URL is
|
|
5
|
+
* plain connection metadata and may surface in tool output; `token` is a
|
|
6
|
+
* fileField — the admin UI / register_access accept token CONTENT, core
|
|
7
|
+
* writes it to a managed file under ~/.dsh-ops/credentials/ and stores the
|
|
8
|
+
* path, so the token itself never sits in the registry, logs, or model
|
|
9
|
+
* context. The provider expands ~ in the token path for the tool's read.
|
|
10
|
+
*
|
|
11
|
+
* No capability probe: the Prometheus HTTP API is read-only by nature
|
|
12
|
+
* (query/query_range), so there is no ro/rw distinction to verify — both
|
|
13
|
+
* tiers serve the same connection parameters.
|
|
14
|
+
*
|
|
15
|
+
* @module @elinpf/dsh-ops-access-prometheus
|
|
16
|
+
*/
|
|
17
|
+
import z from '@deepseek-ai/schemastery';
|
|
18
|
+
import { z as zod } from 'zod';
|
|
19
|
+
import { expandHome, registerAccessProvider } from '@elinpf/dsh-ops-access';
|
|
20
|
+
// ── Plugin identity ───────────────────────────────────────────────────────────
|
|
21
|
+
export const name = 'ops-access-prometheus';
|
|
22
|
+
export const inject = [];
|
|
23
|
+
export const Config = z.object({});
|
|
24
|
+
// ── Provider ─────────────────────────────────────────────────────────────────
|
|
25
|
+
/** Zod schema for one prometheus registry entry (excluding name and envelope fields). */
|
|
26
|
+
export const entrySchema = zod.object({
|
|
27
|
+
url: zod.url({ protocol: /^https?$/, error: 'url must be a valid http(s) URL (e.g. http://prometheus.monitoring:9090)' }),
|
|
28
|
+
token: zod.string().optional(),
|
|
29
|
+
});
|
|
30
|
+
export const provider = {
|
|
31
|
+
kind: 'prometheus',
|
|
32
|
+
schema: entrySchema,
|
|
33
|
+
fieldsDoc: 'url: base URL of the Prometheus server (http(s)); token: optional bearer-token content (paste the token — it is stored as a managed file, the registry keeps only the path)',
|
|
34
|
+
fileFields: ['token'],
|
|
35
|
+
knownLimits: 'Prometheus HTTP API is read-only by nature (query/query_range); this profile carries no k8s permissions — pair it with the k8s profile of the same cluster',
|
|
36
|
+
process(entry) {
|
|
37
|
+
const { url, token } = entry;
|
|
38
|
+
// Strip trailing slashes so the tool can append /api/v1/... cleanly.
|
|
39
|
+
const fields = { url: url.replace(/\/+$/, '') };
|
|
40
|
+
if (token !== undefined)
|
|
41
|
+
fields.token = expandHome(token);
|
|
42
|
+
return fields;
|
|
43
|
+
},
|
|
44
|
+
// A pasted token must be a single line: it lands in an Authorization
|
|
45
|
+
// header, where an interior newline is an invalid-character failure at
|
|
46
|
+
// request time. Same discipline as the ssh password field.
|
|
47
|
+
normalizeTrailingNewline: true,
|
|
48
|
+
validateContent(field, content) {
|
|
49
|
+
if (field !== 'token')
|
|
50
|
+
return null;
|
|
51
|
+
const body = content.endsWith('\n') ? content.slice(0, -1) : content;
|
|
52
|
+
if (body.includes('\n') || body.includes('\r')) {
|
|
53
|
+
return 'a bearer token must be a single line — it is sent verbatim in the Authorization header';
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
// ── Plugin apply ─────────────────────────────────────────────────────────────
|
|
59
|
+
export function apply(ctx) {
|
|
60
|
+
registerAccessProvider(ctx, provider);
|
|
61
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invariant companion for @elinpf/dsh-ops-access-prometheus.
|
|
3
|
+
*
|
|
4
|
+
* @module @elinpf/dsh-ops-access-prometheus/invariant
|
|
5
|
+
*/
|
|
6
|
+
/** Cordis companion plugin name. */
|
|
7
|
+
declare const name = "ops-access-prometheus-invariant";
|
|
8
|
+
/** Service required before the companion can reserve package ownership. */
|
|
9
|
+
declare const inject: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Register this package's invariant companion.
|
|
12
|
+
* @param ctx - Context carrying the invariant service.
|
|
13
|
+
* @returns a promise resolving after registration.
|
|
14
|
+
*/
|
|
15
|
+
declare const apply: (ctx: any) => Promise<void>;
|
|
16
|
+
export { apply, inject, name };
|
package/lib/invariant.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invariant companion for @elinpf/dsh-ops-access-prometheus.
|
|
3
|
+
*
|
|
4
|
+
* @module @elinpf/dsh-ops-access-prometheus/invariant
|
|
5
|
+
*/
|
|
6
|
+
const PACKAGE_NAME = '@elinpf/dsh-ops-access-prometheus';
|
|
7
|
+
/** Cordis companion plugin name. */
|
|
8
|
+
const name = 'ops-access-prometheus-invariant';
|
|
9
|
+
/** Service required before the companion can reserve package ownership. */
|
|
10
|
+
const inject = ['invariants'];
|
|
11
|
+
/**
|
|
12
|
+
* No runtime invariant: this provider owns no session events and no durable
|
|
13
|
+
* shape of its own — it only validates and processes registry fields owned
|
|
14
|
+
* by ops-access core. Content validation is a pure paste guard.
|
|
15
|
+
*/
|
|
16
|
+
const install = () => { };
|
|
17
|
+
/**
|
|
18
|
+
* Register this package's invariant companion.
|
|
19
|
+
* @param ctx - Context carrying the invariant service.
|
|
20
|
+
* @returns a promise resolving after registration.
|
|
21
|
+
*/
|
|
22
|
+
const apply = async (ctx) => {
|
|
23
|
+
ctx.invariants.register(PACKAGE_NAME, install);
|
|
24
|
+
};
|
|
25
|
+
export { apply, inject, name };
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the ops-access-prometheus provider plugin.
|
|
3
|
+
*
|
|
4
|
+
* Types only — no runtime code lives here. Provider values (schema, plugin
|
|
5
|
+
* apply) stay in index.ts.
|
|
6
|
+
*
|
|
7
|
+
* @module @elinpf/dsh-ops-access-prometheus
|
|
8
|
+
*/
|
|
9
|
+
/** One prometheus registry entry (excluding the registry key and envelope fields). */
|
|
10
|
+
export interface PrometheusEntry {
|
|
11
|
+
/** Base URL of the Prometheus server, http(s) only (e.g. https://prometheus.monitoring:9090). */
|
|
12
|
+
url: string;
|
|
13
|
+
/**
|
|
14
|
+
* Path to a file holding the bearer token (optional). Declared in
|
|
15
|
+
* fileFields: the admin UI / register_access accept token CONTENT, core
|
|
16
|
+
* writes it to a managed 0600 file and stores the path. The tool reads the
|
|
17
|
+
* file per call; the token itself never sits in the registry.
|
|
18
|
+
*/
|
|
19
|
+
token?: string;
|
|
20
|
+
}
|
package/lib/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elinpf/dsh-ops-access-prometheus",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Ops access provider for Prometheus — validates prometheus registry entries (server URL + optional bearer-token file) and expands the token path.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./invariant": {
|
|
14
|
+
"types": "./lib/invariant.d.ts",
|
|
15
|
+
"default": "./lib/invariant.js"
|
|
16
|
+
},
|
|
17
|
+
"./types": {
|
|
18
|
+
"types": "./lib/types.d.ts",
|
|
19
|
+
"default": "./lib/types.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"lib/index.js",
|
|
25
|
+
"lib/invariant.js",
|
|
26
|
+
"lib/types.js",
|
|
27
|
+
"lib/**/*.d.ts",
|
|
28
|
+
"cordis.patch.yml"
|
|
29
|
+
],
|
|
30
|
+
"dsh": {
|
|
31
|
+
"bundle": {
|
|
32
|
+
"patch": "./cordis.patch.yml"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
37
|
+
"zod": "^4.4.3"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
41
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.8",
|
|
42
|
+
"@elinpf/dsh-ops-access": "^0.2.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
46
|
+
"typescript": "^5.4.0",
|
|
47
|
+
"vitest": "^4.1.11",
|
|
48
|
+
"@types/node": "^22.0.0",
|
|
49
|
+
"@elinpf/dsh-ops-access": "0.2.0"
|
|
50
|
+
},
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "tsc",
|
|
57
|
+
"typecheck": "tsc --noEmit",
|
|
58
|
+
"test": "vitest run"
|
|
59
|
+
}
|
|
60
|
+
}
|