@amityco/social-plus-vise 0.7.0 → 0.8.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 +275 -95
- package/dist/tools/project.js +25 -1
- package/package.json +1 -1
- package/dist/tools/patch.js +0 -67
package/README.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="
|
|
2
|
+
<img src="./social.plus-vise.png" alt="social.plus Vise" width="320" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">social.plus Vise</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<strong>The standards harness that keeps AI agents on the rails when integrating social.plus SDKs.</strong>
|
|
8
|
+
<strong>The standards harness that keeps AI coding agents on the rails when integrating social.plus SDKs.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@amityco/social-plus-vise"><img src="https://img.shields.io/npm/v/@amityco/social-plus-vise.svg" alt="npm version" /></a>
|
|
13
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/License-Proprietary-blue.svg" alt="License" /></a>
|
|
14
|
+
<a href="https://learn.social.plus"><img src="https://img.shields.io/badge/Docs-learn.social.plus-informational" alt="Docs" /></a>
|
|
9
15
|
</p>
|
|
10
16
|
|
|
11
17
|
<p align="center">
|
|
@@ -14,137 +20,311 @@
|
|
|
14
20
|
|
|
15
21
|
---
|
|
16
22
|
|
|
17
|
-
##
|
|
23
|
+
## Quick Start
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|---|---|
|
|
23
|
-
| **Skill** (`SKILL.md`) | Tells AI agents how to move from user intent → inspect → plan → implement → validate → attest |
|
|
24
|
-
| **CLI** (`vise`) | Deterministic engine: inspects repos, searches docs, validates setup, runs sensors, manages attestations |
|
|
25
|
-
| **MCP adapter** | Optional stdio server for MCP-capable tools |
|
|
25
|
+
```sh
|
|
26
|
+
# 1. Install
|
|
27
|
+
npm install -g @amityco/social-plus-vise
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
# 2. Install the AI skill into your coding tool (pick your host)
|
|
30
|
+
vise install-skill --target claude # Claude Code (personal)
|
|
31
|
+
vise install-skill --target cursor . # Cursor (project-local)
|
|
32
|
+
vise install-skill --target copilot . # GitHub Copilot / VS Code
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
# 3. Inside your project, let your AI agent run the Vise loop
|
|
35
|
+
cd your-app
|
|
36
|
+
vise inspect # detect platform, surface, design signals
|
|
37
|
+
vise plan --request "Add a social feed" # produce a grounded implementation plan
|
|
38
|
+
vise init --request "Add a social feed" # write the sp-vise/ compliance contract
|
|
30
39
|
|
|
31
|
-
|
|
40
|
+
# 4. After the agent makes edits
|
|
41
|
+
vise check # verify the integration against the contract
|
|
42
|
+
vise run-sensors # run your project's own build/typecheck/lint
|
|
43
|
+
```
|
|
32
44
|
|
|
33
|
-
|
|
34
|
-
|---|---|---|---|---|
|
|
35
|
-
| **React / Next.js** | 7 (3 errors) | 2 (warnings) | ❌ FAIL | ✅ PASS |
|
|
36
|
-
| **React Native** | 6 | 2 | ❌ FAIL | ✅ PASS |
|
|
37
|
-
| **Flutter** | 9 | 2 | ❌ FAIL | ✅ PASS |
|
|
38
|
-
| **Android (Kotlin)** | 9 | 0 | ❌ FAIL | ✅ PASS |
|
|
39
|
-
| **iOS (Swift)** | 8 | 0 | ❌ FAIL | ✅ PASS |
|
|
40
|
-
|
|
41
|
-
**Key findings:**
|
|
42
|
-
- Every Pure MCP run ships a **hardcoded secret** (deterministic failure — cannot be attested away)
|
|
43
|
-
- Every Vise run passes CI with **0 deterministic failures**
|
|
44
|
-
- React/RN Vise workspaces: typecheck ✅ build ✅ lint ✅ (Pure MCP fails all three)
|
|
45
|
-
- Vise prevents 5–9 compliance violations per integration in a single pass
|
|
45
|
+
That's it. The skill at `skills/social-plus-vise/SKILL.md` (installed in step 2) teaches your AI agent when to run each command. Skip to [Usage Flow](#usage-flow) for the full picture.
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## What Vise Does
|
|
50
|
+
|
|
51
|
+
Vise is a **local CLI + AI skill** that wraps coding agents in deterministic compliance guardrails when they integrate social.plus SDKs. It inspects your project, grounds the agent in hosted docs, enforces 250+ platform-specific compliance rules, and runs your project's own build/lint/typecheck sensors — all locally. **Your source code never leaves your machine.**
|
|
50
52
|
|
|
51
|
-
|
|
|
53
|
+
| Layer | Purpose |
|
|
52
54
|
|---|---|
|
|
53
|
-
| **
|
|
54
|
-
| **
|
|
55
|
-
| **
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
| **Skill** (`SKILL.md`) | Tells your AI agent when to inspect, plan, fetch docs, edit, validate, and attest |
|
|
56
|
+
| **CLI** (`vise`) | Deterministic engine: inspects repos, searches docs, validates setup, runs sensors, manages attestations |
|
|
57
|
+
| **MCP adapter** | Optional stdio server for MCP-capable tools (Claude Code, Cursor, Codex, VS Code, Copilot) |
|
|
58
|
+
|
|
59
|
+
### Why "Vise"
|
|
60
|
+
|
|
61
|
+
A bench vise holds the workpiece steady so the craftsman's hands are free to shape it. Without one, the workpiece drifts and cuts wander. Vise does the same for AI agents integrating SDKs: it clamps the integration to a known-good position (the real docs, the real project structure, the real compliance rules) so the agent can focus on creative work instead of guessing.
|
|
59
62
|
|
|
60
63
|
---
|
|
61
64
|
|
|
62
|
-
##
|
|
65
|
+
## Supported Platforms
|
|
63
66
|
|
|
64
|
-
|
|
|
65
|
-
|
|
66
|
-
| **
|
|
67
|
-
| **
|
|
68
|
-
| **
|
|
69
|
-
| **
|
|
70
|
-
| **
|
|
71
|
-
| **Session & auth** | session renewal handler, logout on user switch, no anonymous writes |
|
|
72
|
-
| **Notifications** | registration after login, unregister on logout/switch |
|
|
73
|
-
| **Live Objects** | observed domain, lifecycle owner, cleanup, loading/error states |
|
|
74
|
-
| **Logging hygiene** | no secrets in logs, no PII in logs |
|
|
75
|
-
| **Design tokens** | reuse detected tokens from app's existing theme |
|
|
67
|
+
| Platform | Coverage | Sensors |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| **TypeScript / Next.js / React** | ✅ Full | `tsc`, `npm build`, `npm lint`, SDK import smoke |
|
|
70
|
+
| **React Native** | ✅ Full | `tsc`, `npm lint`, SDK import smoke |
|
|
71
|
+
| **Flutter / Dart** | ✅ Full | `flutter analyze`, `flutter test` |
|
|
72
|
+
| **Android (Kotlin)** | ✅ Full | Gradle assemble, unit tests |
|
|
73
|
+
| **iOS (Swift)** | ✅ Full | (static rule checks; runtime sensors WIP) |
|
|
76
74
|
|
|
77
|
-
Each
|
|
75
|
+
Each platform has 50–55 rules across 10 compliance domains (feed, comments, moderation, chat, secrets, session & auth, notifications, live objects, logging hygiene, design tokens).
|
|
78
76
|
|
|
79
|
-
|
|
77
|
+
---
|
|
80
78
|
|
|
81
|
-
##
|
|
79
|
+
## Installation
|
|
82
80
|
|
|
83
|
-
Install
|
|
81
|
+
### Install the CLI
|
|
84
82
|
|
|
85
83
|
```sh
|
|
86
84
|
npm install -g @amityco/social-plus-vise
|
|
87
|
-
vise doctor
|
|
85
|
+
vise doctor # verify install
|
|
88
86
|
```
|
|
89
87
|
|
|
90
|
-
|
|
88
|
+
Or install per-project:
|
|
91
89
|
|
|
92
90
|
```sh
|
|
93
|
-
npm install
|
|
94
|
-
|
|
95
|
-
npm start
|
|
91
|
+
npm install -D @amityco/social-plus-vise
|
|
92
|
+
npx vise --help
|
|
96
93
|
```
|
|
97
94
|
|
|
98
|
-
|
|
95
|
+
### Install the Skill Into Your Coding Tool
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
vise install-skill --target claude
|
|
105
|
-
vise install-skill --target
|
|
106
|
-
vise install-skill --target
|
|
107
|
-
vise install-skill --target
|
|
108
|
-
vise install-skill --target
|
|
109
|
-
vise
|
|
110
|
-
vise
|
|
111
|
-
vise
|
|
112
|
-
vise
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
vise
|
|
123
|
-
vise
|
|
124
|
-
|
|
125
|
-
|
|
97
|
+
The skill is what teaches your AI agent how to use Vise. Pick the matching host:
|
|
98
|
+
|
|
99
|
+
| Host | Install command |
|
|
100
|
+
|---|---|
|
|
101
|
+
| Claude Code (personal scope) | `vise install-skill --target claude` |
|
|
102
|
+
| Claude Code (project scope) | `vise install-skill --target claude-project .` |
|
|
103
|
+
| OpenAI Codex | `vise install-skill --target codex` |
|
|
104
|
+
| Cursor (native skills) | `vise install-skill --target cursor .` |
|
|
105
|
+
| Cursor (legacy rules) | `vise install-skill --target cursor-rules .` |
|
|
106
|
+
| GitHub Copilot / VS Code | `vise install-skill --target vscode .` |
|
|
107
|
+
| Copilot CLI / project | `vise install-skill --target copilot .` |
|
|
108
|
+
| Generic agent project | `vise install-skill --target agents .` |
|
|
109
|
+
| Other coding agents | `vise print-skill` (paste output into the host's project instructions) |
|
|
110
|
+
|
|
111
|
+
The skill is plain Markdown; you can read it any time with `vise print-skill`.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Usage Flow
|
|
116
|
+
|
|
117
|
+
```mermaid
|
|
118
|
+
flowchart LR
|
|
119
|
+
A[User asks AI agent<br/>'Add a social feed'] --> B[Agent runs<br/>vise inspect]
|
|
120
|
+
B --> C[Agent runs<br/>vise plan --request "..."]
|
|
121
|
+
C --> D{Intake<br/>questions?}
|
|
122
|
+
D -->|Yes| E[Agent asks user<br/>for feed target,<br/>design source, etc.]
|
|
123
|
+
D -->|No| F
|
|
124
|
+
E --> F[Agent runs<br/>vise init]
|
|
125
|
+
F --> G[Agent runs<br/>vise search-docs<br/>vise get-doc-page]
|
|
126
|
+
G --> H[Agent edits<br/>your code]
|
|
127
|
+
H --> I[Agent runs<br/>vise check]
|
|
128
|
+
I --> J{Green?}
|
|
129
|
+
J -->|No, fixable| K[Agent fixes<br/>findings]
|
|
130
|
+
K --> I
|
|
131
|
+
J -->|No, attest| L[Agent calls<br/>vise attest with<br/>evidence]
|
|
132
|
+
L --> I
|
|
133
|
+
J -->|Yes| M[Agent runs<br/>vise run-sensors]
|
|
134
|
+
M --> N[Done.<br/>sp-vise/ contract<br/>committed]
|
|
126
135
|
```
|
|
127
136
|
|
|
128
|
-
|
|
137
|
+
The flow above is what the skill teaches your AI agent. You — the human — drive intent and approve edits; the agent runs Vise commands deterministically; Vise grounds the agent in real docs and real compliance rules.
|
|
138
|
+
|
|
139
|
+
---
|
|
129
140
|
|
|
130
|
-
|
|
141
|
+
## CLI Reference
|
|
131
142
|
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
### Project inspection and planning
|
|
144
|
+
|
|
145
|
+
| Command | Purpose |
|
|
146
|
+
|---|---|
|
|
147
|
+
| `vise doctor` | Verify install; print version, install path, docs source |
|
|
148
|
+
| `vise inspect [path]` | Detect platform, monorepo surfaces, design signals, available sensors |
|
|
149
|
+
| `vise plan [path] --request "..."` | Produce a grounded implementation plan with intake questions and docs citations |
|
|
150
|
+
| `vise plan-harness [path] --request "..."` | (Pre-planning step) Build the harness around the request |
|
|
151
|
+
| `vise init [path] --request "..."` | Write the `sp-vise/` compliance contract for this project |
|
|
152
|
+
|
|
153
|
+
### Documentation grounding
|
|
154
|
+
|
|
155
|
+
| Command | Purpose |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `vise search-docs "<query>"` | Search social.plus docs for relevant pages |
|
|
158
|
+
| `vise get-doc-page <path>` | Fetch a specific doc page by path |
|
|
159
|
+
|
|
160
|
+
### Compliance verification
|
|
161
|
+
|
|
162
|
+
| Command | Purpose |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `vise check [path]` | Re-validate against the recorded contract; reports `green`, `needs-attestation`, `deterministic-failures`, `blocked`, or `contract-drift` |
|
|
165
|
+
| `vise check [path] --ci` | Same as `check`, but read-only and exits non-zero unless green (for CI pipelines) |
|
|
166
|
+
| `vise validate [path]` | Run the deterministic validators (subset of `check` that doesn't compare against attestations) |
|
|
167
|
+
| `vise sync [path]` | Persist deterministic-pass evidence to `sp-vise/attestations/` |
|
|
168
|
+
| `vise attest [path] --rule <id> --signer host-agent --confidence high --evidence-file evidence.json --rationale "..."` | Record an attestation when a rule passes through customer-specific architecture that the deterministic check can't see |
|
|
169
|
+
| `vise explain <ruleId>` | Print the rule's rationale, evidence requirements, and remediation guidance |
|
|
170
|
+
| `vise status [path]` | Summarize the current compliance state |
|
|
171
|
+
|
|
172
|
+
### Sensors
|
|
173
|
+
|
|
174
|
+
| Command | Purpose |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `vise run-sensors [path]` | Run detected project commands (npm scripts, Gradle, Flutter, lint, typecheck, SDK import smokes); never executes arbitrary shell |
|
|
177
|
+
| `vise run-sensors [path] --dry-run` | List what would run without executing |
|
|
178
|
+
|
|
179
|
+
### Skill management
|
|
180
|
+
|
|
181
|
+
| Command | Purpose |
|
|
182
|
+
|---|---|
|
|
183
|
+
| `vise install-skill --target <host>` | Install the bundled skill into a coding host (see [Installation](#installation)) |
|
|
184
|
+
| `vise print-skill` | Print the skill markdown to stdout |
|
|
185
|
+
|
|
186
|
+
### Engagement scope (optional contractual metadata)
|
|
187
|
+
|
|
188
|
+
| Command | Purpose |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `vise engagement init [path] [--tier ...] [--customer-id ...] [--scope ...]` | Record the contractual scope for this integration |
|
|
191
|
+
| `vise engagement show [path]` | Print the recorded engagement metadata |
|
|
192
|
+
|
|
193
|
+
### MCP server
|
|
194
|
+
|
|
195
|
+
| Command | Purpose |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `vise mcp` | Start the stdio MCP compatibility adapter |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## MCP Integration
|
|
202
|
+
|
|
203
|
+
MCP-capable hosts can call Vise as structured tool calls instead of shell commands.
|
|
204
|
+
|
|
205
|
+
### Config
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"mcpServers": {
|
|
210
|
+
"social-plus": {
|
|
211
|
+
"command": "vise",
|
|
212
|
+
"args": ["mcp"]
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
134
216
|
```
|
|
135
217
|
|
|
136
|
-
|
|
218
|
+
### Tool names (snake_case per MCP convention)
|
|
137
219
|
|
|
138
|
-
|
|
139
|
-
|
|
220
|
+
`inspect_project`, `plan_harness`, `plan_integration`, `init_compliance`, `check_compliance`, `sync_compliance`, `attest_rule`, `explain_rule`, `init_engagement`, `show_engagement`, `search_docs`, `get_doc_page`, `validate_setup`, `run_sensors`.
|
|
221
|
+
|
|
222
|
+
These are the same operations as the CLI commands above, exposed as MCP tools.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## CI Compliance
|
|
227
|
+
|
|
228
|
+
Add `vise check --ci` to your CI pipeline after committing `sp-vise/compliance.json` to your repository:
|
|
229
|
+
|
|
230
|
+
```yaml
|
|
231
|
+
name: Vise Compliance
|
|
232
|
+
|
|
233
|
+
on:
|
|
234
|
+
pull_request:
|
|
235
|
+
push:
|
|
236
|
+
branches: [main]
|
|
237
|
+
|
|
238
|
+
jobs:
|
|
239
|
+
vise-compliance:
|
|
240
|
+
runs-on: ubuntu-latest
|
|
241
|
+
steps:
|
|
242
|
+
- uses: actions/checkout@v4
|
|
243
|
+
- uses: actions/setup-node@v4
|
|
244
|
+
with:
|
|
245
|
+
node-version: 20
|
|
246
|
+
- run: npm install -g @amityco/social-plus-vise
|
|
247
|
+
- run: vise check . --ci
|
|
140
248
|
```
|
|
141
249
|
|
|
142
|
-
|
|
250
|
+
**Exit codes:**
|
|
251
|
+
|
|
252
|
+
| Code | Meaning |
|
|
253
|
+
|---|---|
|
|
254
|
+
| `0` | All rules pass (deterministic or attested) |
|
|
255
|
+
| `1` | One or more rules need attestation |
|
|
256
|
+
| `2` | One or more rules have deterministic failures |
|
|
257
|
+
| `3` | One or more blockers fired (missing prerequisite, e.g. `google-services.json`) |
|
|
258
|
+
| `4` | Contract drift — rules in `sp-vise/compliance.json` no longer match the current ruleset |
|
|
259
|
+
|
|
260
|
+
`vise check --ci` is read-only. It never updates `sp-vise/`. The JSON output includes a `ci` block with structured details for pipeline logs.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Compliance Contract
|
|
265
|
+
|
|
266
|
+
After `vise init`, your project gets a `sp-vise/` directory. These files become part of your repo and travel through code review:
|
|
267
|
+
|
|
268
|
+
| File | Created by | What it contains |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| `sp-vise/compliance.json` | `vise init` | The rules selected for this integration, the Vise version, the ruleset digest, the target app surface, and an optional engagement link. |
|
|
271
|
+
| `sp-vise/attestations/*.json` | `vise sync` (deterministic) or `vise attest` (host-agent / human) | Per-rule evidence: signer, confidence, rationale, cited files (with source fingerprints for drift detection). |
|
|
272
|
+
| `sp-vise/inspection.json` | `vise init` | The platform, monorepo surface, and design-token signals detected at init time. |
|
|
273
|
+
| `sp-vise/engagement.json` | `vise engagement init` (optional) | Contractual scope: tier, customer ID, contracted outcomes, reviewer assignment. |
|
|
143
274
|
|
|
144
|
-
|
|
275
|
+
**Commit `sp-vise/` to your repo.** `vise check` re-validates against the recorded contract on every run, comparing current code against the recorded attestations. If code changes and breaks a rule, the next `check` reports `deterministic-fail`, `attestation-needed`, or `blocked` — never a silent regression.
|
|
145
276
|
|
|
146
|
-
|
|
147
|
-
|
|
277
|
+
If a rule passes through customer-specific architecture the validator can't see (a DI wrapper, an unconventional file layout, etc.), record an attestation:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
vise attest . \
|
|
281
|
+
--rule typescript.client.region \
|
|
282
|
+
--signer host-agent \
|
|
283
|
+
--confidence high \
|
|
284
|
+
--evidence-file evidence.json \
|
|
285
|
+
--rationale "Region is read from NEXT_PUBLIC_AMITY_REGION env var in lib/amity.ts:6"
|
|
148
286
|
```
|
|
149
287
|
|
|
150
|
-
|
|
288
|
+
Attestation files record source fingerprints (SHA-256 of cited files) so subsequent edits invalidate stale attestations.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Benchmark Headline
|
|
293
|
+
|
|
294
|
+
| Platform | Pure MCP findings | Vise findings | Pure MCP CI | Vise CI |
|
|
295
|
+
|---|---|---|---|---|
|
|
296
|
+
| React / Next.js | 7 (3 errors) | 2 (warnings) | ❌ FAIL | ✅ PASS |
|
|
297
|
+
| React Native | 6 | 2 | ❌ FAIL | ✅ PASS |
|
|
298
|
+
| Flutter | 9 | 2 | ❌ FAIL | ✅ PASS |
|
|
299
|
+
| Android (Kotlin) | 9 | 0 | ❌ FAIL | ✅ PASS |
|
|
300
|
+
| iOS (Swift) | 8 | 0 | ❌ FAIL | ✅ PASS |
|
|
301
|
+
|
|
302
|
+
Measured runs of the same AI agent (Claude Sonnet 4.6) implementing "add a global feed" on each platform, with and without Vise. Without Vise: every run ships a hardcoded API key (a deterministic failure that cannot be attested). With Vise: every run passes CI with zero deterministic failures.
|
|
303
|
+
|
|
304
|
+
For full methodology, per-cell scorecards, and the v0.7 multi-outcome cross-tool validation (chat / comments / push on React + Flutter, plus Antigravity/Gemini cross-tool), see [`benchmarks/RESULTS.md`](./benchmarks/RESULTS.md) in the installed npm package.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Changelog
|
|
309
|
+
|
|
310
|
+
See [`CHANGELOG.md`](./CHANGELOG.md) for the full version history.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Support
|
|
315
|
+
|
|
316
|
+
- **Bugs / feature requests:** contact your social.plus account team or file an issue with your integration partner.
|
|
317
|
+
- **Documentation:** [https://learn.social.plus](https://learn.social.plus)
|
|
318
|
+
- **Skill installation issues:** `vise doctor` prints diagnostic info; share the output with support.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## License
|
|
323
|
+
|
|
324
|
+
Proprietary. See [`LICENSE`](./LICENSE) for terms. social.plus Vise is provided to social.plus customers and integration partners under the same agreement as the social.plus SDK.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
<p align="center">
|
|
329
|
+
Built with <code>vise</code>. Holding compliance steady so agents can build.
|
|
330
|
+
</p>
|
package/dist/tools/project.js
CHANGED
|
@@ -1176,12 +1176,31 @@ function validateLiteralGuardrails(root, platform, sourceContent) {
|
|
|
1176
1176
|
findings.push(finding(`${platform}.feed.target.literal`, "warning", `A hardcoded feed target literal was found: ${feedTarget.name}.`, relativeFile(root, feedTarget.file), "Do not invent or hardcode communityId, targetId, feedId, or channelId. Ask the user for the target or use an existing app-owned selection/create flow."));
|
|
1177
1177
|
}
|
|
1178
1178
|
const inlineApiKey = firstLiteralAssignment(sourceContent, [
|
|
1179
|
+
// Direct literal assignment — apiKey: "literal" or apiKey = "literal".
|
|
1179
1180
|
/\bapiKey\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i,
|
|
1180
1181
|
/\bapi_key\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i,
|
|
1181
1182
|
/\bapi-key\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i,
|
|
1183
|
+
// Env-fallback secret leak patterns — the literal is on the RHS of an
|
|
1184
|
+
// env-lookup fallback, not directly assigned to apiKey. The v0.7 §14
|
|
1185
|
+
// Antigravity benchmark surfaced this gap: Dart's
|
|
1186
|
+
// `apiKey = String.fromEnvironment(KEY, defaultValue: 'literal')` and
|
|
1187
|
+
// JS/TS's `apiKey: process.env.X ?? 'literal'` both shipped a hardcoded
|
|
1188
|
+
// key while the original regex (which requires the literal immediately
|
|
1189
|
+
// after `apiKey [:=]`) saw `String.fromEnvironment(` or `process.env.`
|
|
1190
|
+
// first and missed the literal. The patterns below explicitly walk
|
|
1191
|
+
// through the env-lookup wrapper to the literal default.
|
|
1192
|
+
//
|
|
1193
|
+
// Dart: `defaultValue:` form inside String.fromEnvironment. Uses
|
|
1194
|
+
// non-greedy any-char so the regex can bridge a multi-line argument
|
|
1195
|
+
// list (real Dart code commonly puts each named arg on its own line).
|
|
1196
|
+
/\bapi[-_]?key\b\s*[:=][\s\S]{0,200}?defaultValue\s*:\s*["'`]([^"'`]+)["'`]/i,
|
|
1197
|
+
// JS/TS: process.env.X ?? 'literal' or process.env.X || 'literal'.
|
|
1198
|
+
/\bapi[-_]?key\b\s*[:=][\s\S]{0,200}?(?:process\.env\.[A-Z0-9_]+|import\.meta\.env\.[A-Z0-9_]+)\s*(?:\?\?|\|\|)\s*["'`]([^"'`]+)["'`]/i,
|
|
1199
|
+
// Ternary fallback: `apiKey = X ? 'literal' : ...` captures the truthy branch.
|
|
1200
|
+
/\bapi[-_]?key\b\s*[:=][\s\S]{0,200}?\?\s*["'`]([^"'`]+)["'`]\s*:/i,
|
|
1182
1201
|
]);
|
|
1183
1202
|
if (inlineApiKey && !isAllowedPlaceholder(inlineApiKey.value)) {
|
|
1184
|
-
findings.push(finding(`${platform}.secret.inline-api-key`, "warning", "A social.plus API key appears to be hardcoded in source.", relativeFile(root, inlineApiKey.file), "Use the host app's environment/config pattern instead of committing API keys directly into source files."));
|
|
1203
|
+
findings.push(finding(`${platform}.secret.inline-api-key`, "warning", "A social.plus API key appears to be hardcoded in source.", relativeFile(root, inlineApiKey.file), "Use the host app's environment/config pattern instead of committing API keys directly into source files. The literal is still committed even when wrapped in an env-fallback (e.g. `defaultValue:`, `??`, `||`, ternary)."));
|
|
1185
1204
|
}
|
|
1186
1205
|
// Hardcoded user identity — every benchmark Pure MCP failure mode included
|
|
1187
1206
|
// `userId: "current-user"` or similar. The user identity should come from
|
|
@@ -1346,6 +1365,11 @@ function isAllowedPlaceholder(value) {
|
|
|
1346
1365
|
"api-key",
|
|
1347
1366
|
"your-api-key",
|
|
1348
1367
|
"your_api_key",
|
|
1368
|
+
"your-amity-api-key",
|
|
1369
|
+
"your_amity_api_key",
|
|
1370
|
+
"placeholder",
|
|
1371
|
+
"placeholder-api-key",
|
|
1372
|
+
"placeholder_api_key",
|
|
1349
1373
|
"provided-by-customer",
|
|
1350
1374
|
"customer-provided",
|
|
1351
1375
|
"replace-me",
|
package/package.json
CHANGED
package/dist/tools/patch.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { objectInput, stringField, textResult } from "../types.js";
|
|
2
|
-
export const generateGuardedPatchTool = {
|
|
3
|
-
name: "generate_guarded_patch",
|
|
4
|
-
description: "Yields a structured diff for the host AI agent to apply safely, rejecting any inline API keys or hardcoded IDs.",
|
|
5
|
-
inputSchema: {
|
|
6
|
-
type: "object",
|
|
7
|
-
properties: {
|
|
8
|
-
repoPath: { type: "string" },
|
|
9
|
-
targetFile: { type: "string", description: "Relative path to the file." },
|
|
10
|
-
diffContent: { type: "string", description: "The proposed code change." },
|
|
11
|
-
},
|
|
12
|
-
required: ["repoPath", "targetFile", "diffContent"],
|
|
13
|
-
additionalProperties: false,
|
|
14
|
-
},
|
|
15
|
-
async call(input) {
|
|
16
|
-
const args = objectInput(input);
|
|
17
|
-
const repoPath = stringField(args, "repoPath");
|
|
18
|
-
const targetFile = stringField(args, "targetFile");
|
|
19
|
-
const diffContent = stringField(args, "diffContent");
|
|
20
|
-
// Guardrail: Inline API Keys
|
|
21
|
-
const inlineApiKeyPattern = /\b(api[_-]?key)\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i;
|
|
22
|
-
const apiKeyMatch = inlineApiKeyPattern.exec(diffContent);
|
|
23
|
-
if (apiKeyMatch && !isAllowedPlaceholder(apiKeyMatch[2] ?? "")) {
|
|
24
|
-
return textResult({
|
|
25
|
-
status: "rejected",
|
|
26
|
-
reason: "The patch contains an inline API key. Please use environment variables or a configuration placeholder instead.",
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
// Guardrail: Hardcoded IDs
|
|
30
|
-
const hardcodedIdPattern = /\b(communityId|targetId|feedId|channelId)\b\s*[:=]\s*["'`]([^"'`]+)["'`]/i;
|
|
31
|
-
const idMatch = hardcodedIdPattern.exec(diffContent);
|
|
32
|
-
if (idMatch && !isAllowedPlaceholder(idMatch[2] ?? "")) {
|
|
33
|
-
return textResult({
|
|
34
|
-
status: "rejected",
|
|
35
|
-
reason: `The patch contains a hardcoded literal for ${idMatch[1]}. Please do not invent or hardcode feed targets.`,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return textResult({
|
|
39
|
-
status: "approved",
|
|
40
|
-
repoPath,
|
|
41
|
-
targetFile,
|
|
42
|
-
diffContent,
|
|
43
|
-
instruction: "Host agent: This patch has passed Foundry guardrails. You may now apply this diff securely.",
|
|
44
|
-
});
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
function isAllowedPlaceholder(value) {
|
|
48
|
-
const normalized = value.toLowerCase().trim();
|
|
49
|
-
return [
|
|
50
|
-
"",
|
|
51
|
-
"api-key",
|
|
52
|
-
"your-api-key",
|
|
53
|
-
"your_api_key",
|
|
54
|
-
"provided-by-customer",
|
|
55
|
-
"customer-provided",
|
|
56
|
-
"replace-me",
|
|
57
|
-
"todo",
|
|
58
|
-
"community-id",
|
|
59
|
-
"community_id",
|
|
60
|
-
"target-id",
|
|
61
|
-
"target_id",
|
|
62
|
-
"feed-id",
|
|
63
|
-
"feed_id",
|
|
64
|
-
"channel-id",
|
|
65
|
-
"channel_id",
|
|
66
|
-
].includes(normalized);
|
|
67
|
-
}
|