dsh-env-manager-plugin 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +249 -2
- package/client.js +2581 -0
- package/cordis.patch.yml +4 -0
- package/docs/00-project/current-state.md +246 -0
- package/docs/00-project/glossary.md +215 -0
- package/docs/00-project/project-brief.md +114 -0
- package/docs/00-project/roadmap.md +89 -0
- package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -0
- package/docs/01-architecture/api-verification.md +416 -0
- package/docs/01-architecture/architecture-overview.md +222 -0
- package/docs/01-architecture/data-model.md +930 -0
- package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -0
- package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -0
- package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -0
- package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -0
- package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -0
- package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -0
- package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -0
- package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -0
- package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -0
- package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -0
- package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -0
- package/docs/01-architecture/design.md +666 -0
- package/docs/01-architecture/detailed-design.md +961 -0
- package/docs/01-architecture/implementation-plan.md +323 -0
- package/docs/01-architecture/module-boundaries.md +306 -0
- package/docs/01-architecture/security-model.md +227 -0
- package/docs/01-architecture/storage-contract.md +224 -0
- package/docs/01-architecture/tool-contract.md +438 -0
- package/docs/01-architecture/ui-design.md +587 -0
- package/docs/02-harness/agent-behavior.md +36 -0
- package/docs/02-harness/change-snapshot-policy.md +29 -0
- package/docs/02-harness/client-ui-integration.md +110 -0
- package/docs/02-harness/context-policy.md +43 -0
- package/docs/02-harness/harness-standard.md +91 -0
- package/docs/02-harness/task-execution-policy.md +26 -0
- package/docs/02-harness/verification-policy.md +97 -0
- package/docs/03-openspec/archive-rule.md +25 -0
- package/docs/03-openspec/bugfix-rule.md +30 -0
- package/docs/03-openspec/design-rule.md +33 -0
- package/docs/03-openspec/openspec-usage-guide.md +31 -0
- package/docs/03-openspec/proposal-rule.md +70 -0
- package/docs/03-openspec/spec-rule.md +33 -0
- package/docs/03-openspec/tasks-rule.md +31 -0
- package/docs/04-development/coding-style.md +67 -0
- package/docs/04-development/dependency-policy.md +43 -0
- package/docs/04-development/development-guide.md +85 -0
- package/docs/04-development/directory-convention.md +105 -0
- package/docs/04-development/local-run-guide.md +55 -0
- package/docs/04-development/testing-guide.md +102 -0
- package/docs/05-domain/deployment-template.md +76 -0
- package/docs/05-domain/environment-template.md +165 -0
- package/docs/05-domain/operation-binding-template.md +55 -0
- package/docs/05-domain/operation-record-template.md +55 -0
- package/docs/05-domain/prompt-template.md +90 -0
- package/docs/05-domain/rule-template.md +73 -0
- package/docs/05-domain/service-template.md +39 -0
- package/docs/06-operations/deployment-guide.md +54 -0
- package/docs/06-operations/release.md +188 -0
- package/docs/06-operations/security-policy.md +53 -0
- package/docs/06-operations/troubleshooting.md +91 -0
- package/docs/07-templates/adr-template.md +21 -0
- package/docs/07-templates/bugfix-template.md +11 -0
- package/docs/07-templates/case-template.md +15 -0
- package/docs/07-templates/design-template.md +29 -0
- package/docs/07-templates/proposal-template.md +19 -0
- package/docs/07-templates/spec-template.md +15 -0
- package/docs/07-templates/tasks-template.md +12 -0
- package/docs/99-archive/README.md +13 -0
- package/docs/README.md +142 -0
- package/icon.svg +4 -0
- package/index.js +8 -0
- package/lib/app/app.d.ts +67 -0
- package/lib/app/app.js +494 -0
- package/lib/app/app.js.map +1 -0
- package/lib/config.d.ts +55 -0
- package/lib/config.js +42 -0
- package/lib/config.js.map +1 -0
- package/lib/domain/constants.d.ts +21 -0
- package/lib/domain/constants.js +59 -0
- package/lib/domain/constants.js.map +1 -0
- package/lib/domain/errors.d.ts +20 -0
- package/lib/domain/errors.js +22 -0
- package/lib/domain/errors.js.map +1 -0
- package/lib/domain/schemas.d.ts +28 -0
- package/lib/domain/schemas.js +445 -0
- package/lib/domain/schemas.js.map +1 -0
- package/lib/domain/types.d.ts +412 -0
- package/lib/domain/types.js +2 -0
- package/lib/domain/types.js.map +1 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +89 -0
- package/lib/index.js.map +1 -0
- package/lib/logger.d.ts +8 -0
- package/lib/logger.js +13 -0
- package/lib/logger.js.map +1 -0
- package/lib/memory/bridge.d.ts +18 -0
- package/lib/memory/bridge.js +13 -0
- package/lib/memory/bridge.js.map +1 -0
- package/lib/registry/integrity.d.ts +10 -0
- package/lib/registry/integrity.js +204 -0
- package/lib/registry/integrity.js.map +1 -0
- package/lib/registry/registry.d.ts +14 -0
- package/lib/registry/registry.js +182 -0
- package/lib/registry/registry.js.map +1 -0
- package/lib/resolver/merge.d.ts +23 -0
- package/lib/resolver/merge.js +90 -0
- package/lib/resolver/merge.js.map +1 -0
- package/lib/resolver/resolve.d.ts +18 -0
- package/lib/resolver/resolve.js +288 -0
- package/lib/resolver/resolve.js.map +1 -0
- package/lib/resolver/template.d.ts +10 -0
- package/lib/resolver/template.js +42 -0
- package/lib/resolver/template.js.map +1 -0
- package/lib/router/params.d.ts +3 -0
- package/lib/router/params.js +83 -0
- package/lib/router/params.js.map +1 -0
- package/lib/router/router.d.ts +11 -0
- package/lib/router/router.js +204 -0
- package/lib/router/router.js.map +1 -0
- package/lib/session/session.d.ts +16 -0
- package/lib/session/session.js +64 -0
- package/lib/session/session.js.map +1 -0
- package/lib/skill.d.ts +17 -0
- package/lib/skill.js +56 -0
- package/lib/skill.js.map +1 -0
- package/lib/storage/atomic.d.ts +10 -0
- package/lib/storage/atomic.js +107 -0
- package/lib/storage/atomic.js.map +1 -0
- package/lib/storage/paths.d.ts +10 -0
- package/lib/storage/paths.js +50 -0
- package/lib/storage/paths.js.map +1 -0
- package/lib/storage/records.d.ts +16 -0
- package/lib/storage/records.js +112 -0
- package/lib/storage/records.js.map +1 -0
- package/lib/storage/sessions.d.ts +17 -0
- package/lib/storage/sessions.js +65 -0
- package/lib/storage/sessions.js.map +1 -0
- package/lib/tools/tools.d.ts +14 -0
- package/lib/tools/tools.js +472 -0
- package/lib/tools/tools.js.map +1 -0
- package/lib/transport/http.d.ts +3 -0
- package/lib/transport/http.js +217 -0
- package/lib/transport/http.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +97 -4
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Operation Record Template
|
|
2
|
+
|
|
3
|
+
P1 artifact. V1 defines the type and a null bridge; it does not persist records.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
interface OperationRecord {
|
|
7
|
+
id: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
environmentId: string;
|
|
10
|
+
serviceId?: string;
|
|
11
|
+
deploymentId?: string;
|
|
12
|
+
operation: string;
|
|
13
|
+
skillRef?: string;
|
|
14
|
+
startedAt: string;
|
|
15
|
+
finishedAt?: string;
|
|
16
|
+
outcome: 'success' | 'failure' | 'unknown';
|
|
17
|
+
evidenceRefs: string[];
|
|
18
|
+
summary: string;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## JSON example
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"id": "op-20261101-0001",
|
|
27
|
+
"sessionId": "session-abc",
|
|
28
|
+
"environmentId": "test-a",
|
|
29
|
+
"serviceId": "aicoservice",
|
|
30
|
+
"deploymentId": "deploy-001",
|
|
31
|
+
"operation": "redeploy",
|
|
32
|
+
"skillRef": "redeploy-k8s-service",
|
|
33
|
+
"startedAt": "2026-11-01T03:00:00.000Z",
|
|
34
|
+
"finishedAt": "2026-11-01T03:04:12.000Z",
|
|
35
|
+
"outcome": "success",
|
|
36
|
+
"evidenceRefs": ["evidence:test-a/deploy-001/log-20261101"],
|
|
37
|
+
"summary": "Redeploy completed; pod rollout finished with 2/2 ready"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Rules
|
|
42
|
+
|
|
43
|
+
- `evidenceRefs` are opaque and sanitized; never embed raw logs or secrets.
|
|
44
|
+
- `summary` is redacted and bounded (default 500 characters).
|
|
45
|
+
- The record carries scope ids so memory queries stay scoped.
|
|
46
|
+
- Records are append-only from the plugin's perspective.
|
|
47
|
+
- A record is not an audit replacement for the executing tool's own logging.
|
|
48
|
+
|
|
49
|
+
## Evidence reference format
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
evidence:{environmentId}/{deploymentId}/{kind}-{timestamp}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`kind` is a short token such as `log`, `config` or `check`. The content lives outside the record.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Prompt Template
|
|
2
|
+
|
|
3
|
+
Templates for presenting tool results to an Agent. Keep them compact; do not dump the whole registry.
|
|
4
|
+
|
|
5
|
+
## Service Context
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
# Service Context
|
|
9
|
+
|
|
10
|
+
Environment: {environmentId} ({environmentName}, {environmentCategory})
|
|
11
|
+
Service: {serviceId} ({serviceName})
|
|
12
|
+
Deployment: {deploymentId} ({runtimeMode})
|
|
13
|
+
Status: {status}
|
|
14
|
+
|
|
15
|
+
## Source
|
|
16
|
+
|
|
17
|
+
- Git: {source.gitUrl} ({source.defaultBranch})
|
|
18
|
+
- Module: {source.modulePath}
|
|
19
|
+
- Artifact: {artifact.name} ({artifact.path})
|
|
20
|
+
|
|
21
|
+
## Location
|
|
22
|
+
|
|
23
|
+
{locationSummary}
|
|
24
|
+
|
|
25
|
+
## Log source
|
|
26
|
+
|
|
27
|
+
{logSourceSummary}
|
|
28
|
+
|
|
29
|
+
## Resolved paths
|
|
30
|
+
|
|
31
|
+
| Field | Value | Defined by | Inputs |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
{pathRows}
|
|
34
|
+
|
|
35
|
+
## Class location
|
|
36
|
+
|
|
37
|
+
{classLocationSummary}
|
|
38
|
+
|
|
39
|
+
## Credentials
|
|
40
|
+
|
|
41
|
+
- {ref} — configured: {configured} (source: {source})
|
|
42
|
+
|
|
43
|
+
## Diagnostics
|
|
44
|
+
|
|
45
|
+
{diagnostics}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Rules:
|
|
49
|
+
|
|
50
|
+
- Mark derived values as derived; do not imply they exist.
|
|
51
|
+
- Show provenance for every path, because that is how users debug overrides.
|
|
52
|
+
- Never include credential values.
|
|
53
|
+
|
|
54
|
+
## Operation Resolution
|
|
55
|
+
|
|
56
|
+
```markdown
|
|
57
|
+
# Operation Resolution
|
|
58
|
+
|
|
59
|
+
Operation: {operation}
|
|
60
|
+
Context: {environmentId} / {serviceId} / {deploymentId}
|
|
61
|
+
Binding: {matchedBindingId} (level: {matchLevel})
|
|
62
|
+
Skill: {skill.name} (available: {skill.available})
|
|
63
|
+
Policy: requiresApproval={policy.requiresApproval}, allowProduction={policy.allowProduction}
|
|
64
|
+
|
|
65
|
+
## Parameters
|
|
66
|
+
|
|
67
|
+
- {key}: {value}
|
|
68
|
+
|
|
69
|
+
## Diagnostics
|
|
70
|
+
|
|
71
|
+
{diagnostics}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Rules:
|
|
75
|
+
|
|
76
|
+
- If the result is a conflict, list every candidate binding and its level.
|
|
77
|
+
- If the Skill is unavailable, state why and do not suggest an alternative Skill.
|
|
78
|
+
- Never present a routing result as permission to execute.
|
|
79
|
+
|
|
80
|
+
## Environment Summary
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
# Environments
|
|
84
|
+
|
|
85
|
+
| Environment | Category | Hosts | Clusters | Services |
|
|
86
|
+
|---|---|---|---|---|
|
|
87
|
+
{rows}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Keep list output under 50 rows; point the reader at `env_get` for detail.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Rule Profile Template
|
|
2
|
+
|
|
3
|
+
Copy into `<dataDir>/rules/<id>.yaml`.
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
id: java-common
|
|
7
|
+
schemaVersion: 1
|
|
8
|
+
description: Common Java service paths, log sources and class locations
|
|
9
|
+
|
|
10
|
+
variables:
|
|
11
|
+
installRoot: /opt/company/services
|
|
12
|
+
timezone: Asia/Shanghai
|
|
13
|
+
|
|
14
|
+
paths:
|
|
15
|
+
serviceHome: ${installRoot}/${service.id}
|
|
16
|
+
jar: ${paths.serviceHome}/lib/${service.artifact.name}
|
|
17
|
+
logDir: ${paths.serviceHome}/logs
|
|
18
|
+
applicationLog: ${paths.logDir}/${service.id}.log
|
|
19
|
+
configDir: ${paths.serviceHome}/config
|
|
20
|
+
|
|
21
|
+
logSources:
|
|
22
|
+
native:
|
|
23
|
+
kind: file
|
|
24
|
+
path: ${paths.applicationLog}
|
|
25
|
+
docker:
|
|
26
|
+
kind: container-stdout
|
|
27
|
+
container: ${deployment.location.containerName}
|
|
28
|
+
kubernetes:
|
|
29
|
+
kind: pod-logs
|
|
30
|
+
namespace: ${deployment.location.namespace}
|
|
31
|
+
workload: ${deployment.location.workload.name}
|
|
32
|
+
|
|
33
|
+
classLocations:
|
|
34
|
+
native:
|
|
35
|
+
kind: deployed-dir
|
|
36
|
+
path: ${paths.serviceHome}/classes
|
|
37
|
+
kubernetes:
|
|
38
|
+
kind: jar-entry
|
|
39
|
+
path: ${paths.jar}
|
|
40
|
+
entryPrefix: com/company/aico
|
|
41
|
+
|
|
42
|
+
createdAt: 2026-11-01T03:00:00.000Z
|
|
43
|
+
updatedAt: 2026-11-01T03:00:00.000Z
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Template syntax
|
|
47
|
+
|
|
48
|
+
Allowed:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
${installRoot}
|
|
52
|
+
${paths.serviceHome}
|
|
53
|
+
${service.id}
|
|
54
|
+
${deployment.location.namespace}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Forbidden:
|
|
58
|
+
|
|
59
|
+
- function calls, arithmetic, conditionals
|
|
60
|
+
- environment variable access
|
|
61
|
+
- shell or command substitution
|
|
62
|
+
- JavaScript
|
|
63
|
+
|
|
64
|
+
## Notes
|
|
65
|
+
|
|
66
|
+
- A path may reference another path; cycles are errors.
|
|
67
|
+
- Undefined references are errors, not empty strings.
|
|
68
|
+
- The only valid form is `${identifier(.identifier)*}`, capped at 2048 characters;
|
|
69
|
+
anything else (missing brace, operators, spaces) is `RULE_TEMPLATE_INVALID`.
|
|
70
|
+
- Resolved paths containing `..` are rejected.
|
|
71
|
+
- `classLocations` distinguishes build output, deployed directories and jar entries.
|
|
72
|
+
- Only the deployment's `runtimeMode` entry is resolved by `env_resolve`.
|
|
73
|
+
- Overrides: environment `ruleOverrides`, then deployment `variables` and `ruleOverrides`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Service Template
|
|
2
|
+
|
|
3
|
+
Copy into `<dataDir>/services/<id>.yaml` and replace the example values.
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
id: aicoservice
|
|
7
|
+
schemaVersion: 1
|
|
8
|
+
name: Aico Service
|
|
9
|
+
aliases: [aicoservice]
|
|
10
|
+
category: backend
|
|
11
|
+
description: Core AI coordination service
|
|
12
|
+
|
|
13
|
+
git:
|
|
14
|
+
url: https://git.example.internal/team/aicoservice.git
|
|
15
|
+
defaultBranch: main
|
|
16
|
+
modulePath: / # monorepo subpath, omit when not needed
|
|
17
|
+
|
|
18
|
+
build:
|
|
19
|
+
tool: maven # maven | gradle | npm | custom
|
|
20
|
+
command: mvn -DskipTests package
|
|
21
|
+
|
|
22
|
+
artifact:
|
|
23
|
+
name: aicoservice.jar
|
|
24
|
+
path: ${paths.serviceHome}/lib/${service.artifact.name}
|
|
25
|
+
|
|
26
|
+
deployModes: [native, docker, kubernetes]
|
|
27
|
+
ruleProfileRefs: [java-common, company-default] # order matters; later wins
|
|
28
|
+
|
|
29
|
+
createdAt: 2026-11-01T03:00:00.000Z
|
|
30
|
+
updatedAt: 2026-11-01T03:00:00.000Z
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Notes
|
|
34
|
+
|
|
35
|
+
- Services are environment-independent. Placement belongs in a deployment binding.
|
|
36
|
+
- `ruleProfileRefs` are applied in order; when two profiles define the same field, the later one wins.
|
|
37
|
+
- `deployModes` must include every runtime mode used by its deployment bindings.
|
|
38
|
+
- `artifact.name` is commonly interpolated by rule profiles as `${service.artifact.name}`.
|
|
39
|
+
- No credentials here. A service-level credential is not modelled in V1.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Deployment Guide
|
|
2
|
+
|
|
3
|
+
## Install as a Local Bundle
|
|
4
|
+
|
|
5
|
+
In a DSH session, call the `plugin_manager` tool:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
action: install_bundle
|
|
9
|
+
target: <absolute path to this repository>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Restart DSH if needed.
|
|
13
|
+
|
|
14
|
+
## Verify
|
|
15
|
+
|
|
16
|
+
1. Ask `plugin_manager` for `action: list_bundles` and confirm the bundle appears.
|
|
17
|
+
2. Confirm it is active, not `overridden` or `restart-required`.
|
|
18
|
+
3. Call `env_list` from the Agent; a fresh install returns an empty list.
|
|
19
|
+
4. Open the **Environment Manager** entry in the sidebar and confirm the Overview
|
|
20
|
+
counts render.
|
|
21
|
+
5. Optional transport check:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
curl -s -X POST http://127.0.0.1:<port>/env-manager/api \
|
|
25
|
+
-H 'content-type: application/json' \
|
|
26
|
+
-H 'x-env-manager-request: 1' \
|
|
27
|
+
-d '{"op":"meta"}'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Without the header the route returns 403; that is the expected control.
|
|
31
|
+
|
|
32
|
+
## Upgrade
|
|
33
|
+
|
|
34
|
+
1. Pull the latest changes.
|
|
35
|
+
2. `npm install && npm run build`.
|
|
36
|
+
3. Reinstall the bundle with `plugin_manager`.
|
|
37
|
+
4. Restart DSH so the Host module generation is fresh.
|
|
38
|
+
5. Run `env_validate` and review diagnostics.
|
|
39
|
+
|
|
40
|
+
Registry data is untouched by an upgrade. A `schemaVersion` change requires a migration; V1 has none.
|
|
41
|
+
|
|
42
|
+
## Remove
|
|
43
|
+
|
|
44
|
+
Call `plugin_manager` with `action: remove_bundle` and `target: dsh-env-manager-plugin`.
|
|
45
|
+
|
|
46
|
+
Registry data under `dataDir` is not deleted. Back it up if you may reinstall later.
|
|
47
|
+
|
|
48
|
+
## Rollback
|
|
49
|
+
|
|
50
|
+
1. Reinstall the previous checkout.
|
|
51
|
+
2. Restart DSH.
|
|
52
|
+
3. Restore `dataDir` from the backup if the previous version wrote incompatible records.
|
|
53
|
+
|
|
54
|
+
V1 accepts only `schemaVersion: 1`; records written by an unknown version are skipped with a warning rather than corrupted.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Release Guide
|
|
2
|
+
|
|
3
|
+
发布由 [`.github/workflows/release.yml`](../../.github/workflows/release.yml) 自动完成:
|
|
4
|
+
推送 `v*` tag 后,在 Windows runner 上运行 typecheck、build、test,打包 npm tarball,
|
|
5
|
+
通过 npm Trusted Publisher(OIDC)发布到 npm,并创建 GitHub Release。
|
|
6
|
+
|
|
7
|
+
## 包名说明
|
|
8
|
+
|
|
9
|
+
npm 上的 `dsh-env-manager` 已经被另一个**不同功能的包**占用,因此本插件发布为:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
dsh-env-manager-plugin
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
插件运行时 id、Skill 名和数据目录仍是 `dsh-env-manager`;只有 npm 包名和
|
|
16
|
+
`cordis.patch.yml` 的模块名使用 `dsh-env-manager-plugin`。
|
|
17
|
+
|
|
18
|
+
## 触发方式
|
|
19
|
+
|
|
20
|
+
### 推荐:推送 tag
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
git tag -a v0.1.0 -m "v0.1.0"
|
|
24
|
+
git push origin v0.1.0
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
也可以一次推送提交和 tag:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
git push origin main --follow-tags
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`--follow-tags` 只推送 annotated tag;如果使用 lightweight tag,必须显式
|
|
34
|
+
`git push origin v0.1.0`。
|
|
35
|
+
|
|
36
|
+
### 手动触发
|
|
37
|
+
|
|
38
|
+
GitHub → Actions → Release → Run workflow,输入已存在的 tag(例如 `v0.1.0`)。
|
|
39
|
+
|
|
40
|
+
## 发布前检查
|
|
41
|
+
|
|
42
|
+
1. `package.json` 的 `version` 必须与 tag 去掉 `v` 后完全一致;不一致时 workflow 会在
|
|
43
|
+
第一步失败。
|
|
44
|
+
2. 本地运行 `npm run check`(typecheck + build + test + client 语法检查)。
|
|
45
|
+
3. 确认 `lib/` 已重新构建;`npm pack` 的 `prepack` 也会构建,但本地检查应提前暴露错误。
|
|
46
|
+
4. 确认 `README.md`、`docs/00-project/current-state.md` 已更新。
|
|
47
|
+
5. 检查 tarball:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
npm pack --dry-run
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
确认包含 `index.js`、`client.js`、`cordis.patch.yml`、`lib/`、`locale/`、`icon.svg`、
|
|
54
|
+
`README.md`、`LICENSE` 和 `docs/`。
|
|
55
|
+
6. 提交所有发布内容,再打 tag;tag 指向的 commit 应包含完整发布内容。
|
|
56
|
+
|
|
57
|
+
## 首次发布与 Trusted Publisher
|
|
58
|
+
|
|
59
|
+
Trusted Publisher 只能在 npm 包已经存在后绑定,因此**第一次发布需要先手动完成**。
|
|
60
|
+
之后的版本由 GitHub Actions 自动发布,不需要 `NPM_TOKEN`。
|
|
61
|
+
|
|
62
|
+
### 1. 首次发布(bootstrap)
|
|
63
|
+
|
|
64
|
+
Trusted Publisher 只能在包存在后绑定,因此第一次用一个不会占用 `latest` 的
|
|
65
|
+
placeholder 版本把包名注册下来:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
npm version 0.0.0-stage --no-git-tag-version
|
|
69
|
+
npm publish --access public --tag stage
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
这一步需要交互式 2FA/OTP;不能用没有 OTP 的自动化 shell 代替。发布成功后,
|
|
73
|
+
npm 上会出现 `dsh-env-manager-plugin@0.0.0-stage`,当前账号成为 maintainer;
|
|
74
|
+
`stage` tag 不会覆盖 `latest`。
|
|
75
|
+
|
|
76
|
+
然后把版本恢复为本次正式发布版本:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npm version 0.1.0 --no-git-tag-version
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> 如果 `npm publish` 报 `EOTP`,请在交互终端完成 2FA;不要把一次性密码写进脚本或仓库。
|
|
83
|
+
> 也可以使用 `0.0.0-bootstrap`,只要 tag 用 `stage` 而不是 `latest`。
|
|
84
|
+
|
|
85
|
+
### 2. 绑定 GitHub Actions
|
|
86
|
+
|
|
87
|
+
打开 npmjs.com → `dsh-env-manager-plugin` → Settings → Trusted publishing →
|
|
88
|
+
Add GitHub Actions publisher:
|
|
89
|
+
|
|
90
|
+
| 字段 | 值 |
|
|
91
|
+
|---|---|
|
|
92
|
+
| Organization or user | `zhiwuli0228` |
|
|
93
|
+
| Repository | `dsh-env-manager` |
|
|
94
|
+
| Workflow filename | `release.yml` |
|
|
95
|
+
| Environment | 留空 |
|
|
96
|
+
|
|
97
|
+
绑定后可以检查:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
npm trust list dsh-env-manager-plugin
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`npm trust` 也可能要求 2FA;失败时以 npm 网页设置页为准。
|
|
104
|
+
|
|
105
|
+
### 3. 之后的自动发布
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
git tag -a v0.1.1 -m "v0.1.1"
|
|
109
|
+
git push origin v0.1.1
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
workflow 使用 `id-token: write` 获取 OIDC token,执行:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
npm publish --access public --provenance
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
不需要 `NPM_TOKEN`,也不需要 `.npmrc`。`--provenance` 只生成供应链证明;
|
|
119
|
+
它本身不授予发布权限,授权来自 npm 侧的 Trusted Publisher 绑定。
|
|
120
|
+
|
|
121
|
+
### 备选:NPM_TOKEN
|
|
122
|
+
|
|
123
|
+
如果暂时不绑定 Trusted Publisher,可以创建 npm Automation token,配置为仓库
|
|
124
|
+
secret `NPM_TOKEN`,并在 publish 前写入 `.npmrc`。当前 workflow 不使用该方案;
|
|
125
|
+
不要把 token 提交到仓库。
|
|
126
|
+
|
|
127
|
+
## Workflow 步骤
|
|
128
|
+
|
|
129
|
+
1. Checkout tag。
|
|
130
|
+
2. 校验 tag 与 `package.json` 版本。
|
|
131
|
+
3. `npm ci`。
|
|
132
|
+
4. `npm run check`(typecheck + build + test + client 语法检查)。
|
|
133
|
+
5. `npm pack`,生成 `dsh-env-manager-plugin-<version>.tgz`。
|
|
134
|
+
6. 升级 npm CLI,然后用 Trusted Publisher / OIDC 发布到 npm。
|
|
135
|
+
7. 创建 GitHub Release,自动生成 release notes,并上传 tarball。
|
|
136
|
+
|
|
137
|
+
## 权限
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
permissions:
|
|
141
|
+
contents: write # 创建 Release
|
|
142
|
+
id-token: write # Trusted Publisher + npm provenance
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
不要使用 `write-all`。
|
|
146
|
+
|
|
147
|
+
## 发布后验证
|
|
148
|
+
|
|
149
|
+
1. 等待 registry 传播(通常 1–5 分钟):
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
npm view dsh-env-manager-plugin version
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
2. 验证元数据:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
npm view dsh-env-manager-plugin@0.1.0 dist.shasum dist.integrity gitHead dist.attestations
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`gitHead` 应等于 tag commit;provenance 的 `predicateType` 应为
|
|
162
|
+
`https://slsa.dev/provenance/v1`。
|
|
163
|
+
|
|
164
|
+
3. 验证 Release:
|
|
165
|
+
|
|
166
|
+
```sh
|
|
167
|
+
gh release view v0.1.0
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
确认 `dsh-env-manager-plugin-0.1.0.tgz` 附件存在。
|
|
171
|
+
|
|
172
|
+
4. 更新 `docs/00-project/current-state.md` 的发布状态和测试计数。
|
|
173
|
+
|
|
174
|
+
## 常见失败
|
|
175
|
+
|
|
176
|
+
- **`private: true` / npm 拒绝发布**:当前 `package.json` 已移除 `private`。
|
|
177
|
+
- **tag 与版本不一致**:先改 `package.json`,提交后再打 tag。
|
|
178
|
+
- **npm 版本已存在**:npm 不允许覆盖同版本;提升版本并重新打 tag,不要重复 publish。
|
|
179
|
+
- **`EOTP` / 2FA**:交互式发布需要 OTP;CI 使用 Trusted Publisher。
|
|
180
|
+
- **`ENEEDAUTH`**:没有 token 且 Trusted Publisher 未绑定,或 workflow 缺少
|
|
181
|
+
`id-token: write`。
|
|
182
|
+
- **`E403` / 版本已存在**:先确认 `npm view`,不要立即重试。
|
|
183
|
+
- **`npm view` 仍显示旧版本**:registry 传播/缓存,先看 workflow 日志。
|
|
184
|
+
- **首次 workflow 发布失败**:Trusted Publisher 必须在包存在且绑定后才能用;
|
|
185
|
+
先完成上面的 bootstrap。
|
|
186
|
+
- **lightweight tag 没被推送**:用 annotated tag 或显式 `git push origin <tag>`。
|
|
187
|
+
- **Release 已存在**:`softprops/action-gh-release` 会更新已有 Release;
|
|
188
|
+
需要全新发布时使用新 tag。
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Security Policy (Operations)
|
|
2
|
+
|
|
3
|
+
Operational rules for users and agents. Design rationale is in
|
|
4
|
+
[security-model.md](../01-architecture/security-model.md).
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Credentials
|
|
9
|
+
|
|
10
|
+
1. Every host, cluster, endpoint and future adapter uses a `credentialRef`.
|
|
11
|
+
2. Never write a password, token, private key or kubeconfig into a registry file, a test fixture or a Git commit.
|
|
12
|
+
3. The plugin reports only `configured`, `missing` or `unavailable`.
|
|
13
|
+
4. If a credential is missing, fix the reference; do not paste the value into the registry.
|
|
14
|
+
|
|
15
|
+
## 2. Production changes
|
|
16
|
+
|
|
17
|
+
1. `category: production` environments are gated.
|
|
18
|
+
2. Operation bindings that target production must set `allowProduction: true` explicitly; otherwise routing fails.
|
|
19
|
+
3. Management writes that affect production records require approval when performed by
|
|
20
|
+
the Agent.
|
|
21
|
+
4. The UI writes as actor `'ui'` and is denied for production records unless
|
|
22
|
+
`writePolicy.allowUiProductionWrites` is enabled.
|
|
23
|
+
5. A denied approval is final for that attempt; nothing is written.
|
|
24
|
+
|
|
25
|
+
## 3. Rule templates
|
|
26
|
+
|
|
27
|
+
1. Only `${...}` interpolation is allowed.
|
|
28
|
+
2. Do not attempt to inject JavaScript, shell or environment lookups. They are rejected.
|
|
29
|
+
3. If a path must differ per environment, use an override, not a new template language feature.
|
|
30
|
+
4. Review rule profiles that resolve to sensitive directories. V1 does not read them, but future adapters will.
|
|
31
|
+
|
|
32
|
+
## 4. Data handling
|
|
33
|
+
|
|
34
|
+
1. `data/` is git-ignored. Do not commit registry data.
|
|
35
|
+
2. Do not place real internal hostnames, IPs or URLs in `tests/fixtures/`.
|
|
36
|
+
3. Redact command output and evidence before recording it.
|
|
37
|
+
4. Keep summaries short; evidence lives behind opaque references.
|
|
38
|
+
|
|
39
|
+
## 5. Sharing and scope
|
|
40
|
+
|
|
41
|
+
1. Registry data is profile-global. Treat it as internal documentation.
|
|
42
|
+
2. Session defaults are per session. Do not design flows that rely on a global default.
|
|
43
|
+
3. Memory entries must carry environment/service/deployment scope.
|
|
44
|
+
4. A conclusion from one environment is not a global rule.
|
|
45
|
+
|
|
46
|
+
## 6. Incident handling
|
|
47
|
+
|
|
48
|
+
If a secret is committed by mistake:
|
|
49
|
+
|
|
50
|
+
1. Rotate the secret immediately.
|
|
51
|
+
2. Remove it from Git history, not only from the working tree.
|
|
52
|
+
3. Record the incident outside this repository.
|
|
53
|
+
4. Add a check or test that would have caught it.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
## Plugin is not visible after install
|
|
4
|
+
|
|
5
|
+
1. Ask `plugin_manager` for `action: list_bundles` — confirm the bundle is listed.
|
|
6
|
+
2. Check the activation result for `failed` / `overridden` / `restart-required`.
|
|
7
|
+
3. Restart DSH.
|
|
8
|
+
|
|
9
|
+
## Host build fails
|
|
10
|
+
|
|
11
|
+
1. Run `npm run build` and read the first error, not the count.
|
|
12
|
+
2. Confirm `tsconfig.json` exists and `outDir` is `lib`.
|
|
13
|
+
3. Check that `index.js` re-exports `./lib/index.js` and the file exists.
|
|
14
|
+
|
|
15
|
+
## Tools are not registered
|
|
16
|
+
|
|
17
|
+
1. Confirm the bundle is active.
|
|
18
|
+
2. Check Host logs for an exception in `apply`.
|
|
19
|
+
3. Call `env_list`: an empty list is correct on a fresh install; an unknown tool means registration failed.
|
|
20
|
+
4. Reinstall after every Host rebuild; Host code changes need a fresh module generation.
|
|
21
|
+
|
|
22
|
+
## Client panel does not appear
|
|
23
|
+
|
|
24
|
+
1. Verify `client.js` is listed in `files` and exported as `./client`.
|
|
25
|
+
2. Check the browser console for module-loader errors.
|
|
26
|
+
3. Verify the slot id and name match a live slot.
|
|
27
|
+
4. Reinstall the bundle after editing `client.js`.
|
|
28
|
+
|
|
29
|
+
## Registry loads with warnings
|
|
30
|
+
|
|
31
|
+
Warnings are expected when a file is invalid. They name the file and the field.
|
|
32
|
+
|
|
33
|
+
1. Fix the YAML or the field.
|
|
34
|
+
2. Run `env_validate` again.
|
|
35
|
+
3. Invalid files are never deleted automatically, so the data is still on disk.
|
|
36
|
+
|
|
37
|
+
## `env_resolve` returns `RULE_UNDEFINED_VARIABLE`
|
|
38
|
+
|
|
39
|
+
1. The message names the field and the missing variable.
|
|
40
|
+
2. Check that the variable exists in a referenced rule profile or in an environment/deployment override.
|
|
41
|
+
3. Remember that only the deployment's runtime fields are in scope.
|
|
42
|
+
|
|
43
|
+
## `RULE_CYCLE`
|
|
44
|
+
|
|
45
|
+
Two or more fields reference each other. Break the cycle in the rule profile; the message contains the cycle path.
|
|
46
|
+
|
|
47
|
+
## `RULE_PATH_TRAVERSAL`
|
|
48
|
+
|
|
49
|
+
A resolved path contains a `..` segment. Fix the template; traversal is rejected by design.
|
|
50
|
+
|
|
51
|
+
## `DEPLOYMENT_AMBIGUOUS`
|
|
52
|
+
|
|
53
|
+
The service has several bindings in the environment. Pass `deploymentId` explicitly.
|
|
54
|
+
|
|
55
|
+
## `BINDING_CONFLICT`
|
|
56
|
+
|
|
57
|
+
Two enabled bindings match at the same level. Disable one, narrow one, or merge them. The plugin will not choose for you.
|
|
58
|
+
|
|
59
|
+
## `SKILL_UNAVAILABLE`
|
|
60
|
+
|
|
61
|
+
The bound Skill is not registered, or its source/provider does not match. Install or correct the Skill; do not add a fallback binding that changes the environment silently.
|
|
62
|
+
|
|
63
|
+
## `POLICY_DENIED`
|
|
64
|
+
|
|
65
|
+
Either the environment is production and the binding does not allow it, or an approval was denied. Fix the policy deliberately, not by flipping flags in a hurry.
|
|
66
|
+
|
|
67
|
+
## Session default is not remembered
|
|
68
|
+
|
|
69
|
+
If the tool reports `persisted: false`, the state file could not be written. Check `dataDir` permissions and the `sessions/` directory. The value is kept in a process-local cache, so it still works for this process but is lost on restart.
|
|
70
|
+
|
|
71
|
+
## Panel says "Cannot reach the Host"
|
|
72
|
+
|
|
73
|
+
1. Confirm the bundle is active and the Host is running.
|
|
74
|
+
2. Reload the page; the panel uses a same-origin `POST /env-manager/api`.
|
|
75
|
+
3. In the browser console, a 403 means the request header or origin check failed — this is the transport control, not a bug.
|
|
76
|
+
4. A 404 means the route was not registered; reinstall the bundle after a Host rebuild.
|
|
77
|
+
|
|
78
|
+
## Panel write is denied for a production record
|
|
79
|
+
|
|
80
|
+
`writePolicy.allowUiProductionWrites` defaults to `false`. Edit the YAML through the Agent (`env_save`, with approval) or change the policy deliberately.
|
|
81
|
+
|
|
82
|
+
## Panel shows "Unknown" skill availability
|
|
83
|
+
|
|
84
|
+
The Skill catalog was absent or incomplete when the operation was resolved. Check that the Skill registry is available; the router never assumes a missing catalog means "available".
|
|
85
|
+
|
|
86
|
+
## Storage errors
|
|
87
|
+
|
|
88
|
+
1. Verify write permission on `dataDir`.
|
|
89
|
+
2. Check that `dataDir` is not inside a read-only workspace.
|
|
90
|
+
3. Confirm the file name matches the record `id`.
|
|
91
|
+
4. Check `schemaVersion`; V1 only reads `1`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ADR-{NNNN}: Title
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Proposed / Accepted / Superseded
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
What is the issue that we're seeing that is motivating this decision?
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
What is the change that we're proposing or have accepted?
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
What becomes easier or more difficult to do because of this change?
|
|
18
|
+
|
|
19
|
+
## Alternatives Considered
|
|
20
|
+
|
|
21
|
+
What other approaches were considered and why were they rejected?
|