@vantageos/backend-doctor 0.1.13 → 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.md +19 -2
- package/dist/args.d.ts +16 -0
- package/dist/args.js +54 -0
- package/dist/build-stamp.d.ts +13 -0
- package/dist/build-stamp.js +76 -0
- package/dist/build-stamp.json +4 -0
- package/dist/caller-resolution.d.ts +222 -0
- package/dist/caller-resolution.js +1195 -0
- package/dist/cli.js +217 -10
- package/dist/coverage-cli.js +8 -0
- package/dist/crud-coverage.d.ts +81 -0
- package/dist/crud-coverage.js +375 -0
- package/dist/detectors/oracle-axis1.d.ts +5 -3
- package/dist/detectors/oracle-axis1.js +24 -15
- package/dist/detectors/oracle-axis2.js +5 -6
- package/dist/detectors/predicates.d.ts +3 -0
- package/dist/detectors/predicates.js +81 -16
- package/dist/detectors/shared.js +5 -5
- package/dist/detectors/source/_scan.js +6 -1
- package/dist/detectors/source/backfill.js +9 -1
- package/dist/detectors/source/guard-helper-flow.d.ts +112 -0
- package/dist/detectors/source/guard-helper-flow.js +1173 -0
- package/dist/detectors/source/identity.d.ts +51 -2
- package/dist/detectors/source/identity.js +815 -14
- package/dist/detectors/source/isolation.d.ts +11 -1
- package/dist/detectors/source/isolation.js +106 -25
- package/dist/detectors/source/jobs.js +165 -2
- package/dist/detectors/source/readbudget.d.ts +1 -0
- package/dist/detectors/source/readbudget.js +67 -4
- package/dist/detectors/source/security.d.ts +16 -0
- package/dist/detectors/source/security.js +225 -7
- package/dist/detectors/source/write-isolation.d.ts +8 -1
- package/dist/detectors/source/write-isolation.js +64 -30
- package/dist/detectors/standard/r46-returns-validator.d.ts +8 -0
- package/dist/detectors/standard/r46-returns-validator.js +45 -14
- package/dist/detectors/structural.js +14 -10
- package/dist/oracle.d.ts +92 -3
- package/dist/oracle.js +229 -12
- package/dist/registry.d.ts +7 -0
- package/dist/registry.js +48 -6
- package/dist/report.d.ts +11 -1
- package/dist/report.js +15 -2
- package/dist/state-rank.d.ts +5 -0
- package/dist/state-rank.js +9 -0
- package/dist/tally.d.ts +35 -0
- package/dist/tally.js +76 -8
- package/dist/target.d.ts +32 -0
- package/dist/target.js +173 -0
- package/fixtures/cr1-classes/_generated/api.d.ts +24 -0
- package/fixtures/cr1-classes/surface.ts +206 -0
- package/fixtures/cr1-empty/nothing.ts +1 -0
- package/fixtures/cr1-refusal-on-resolved/_generated/api.d.ts +24 -0
- package/fixtures/cr1-refusal-on-resolved/doors.ts +180 -0
- package/fixtures/cr1-refusal-on-resolved/lib/auth.ts +104 -0
- package/fixtures/r34-vp-auth-30e821b/auth-805-812.ts.txt +8 -0
- package/fixtures/r34-vp-auth-30e821b/auth-878-890.ts.txt +13 -0
- package/fixtures/vp-writer-tier-1e4ab36.csv +55 -0
- package/package.json +2 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// CR-1 fixture — public doors gated the way vantage-peers 58ed649 gates the OKF
|
|
2
|
+
// export/import doors (okfBundleNode.ts:244-276, okfBundleDurable.ts:110-132,
|
|
3
|
+
// okfBundleNode.ts:783-793), plus the negative poles that must stay FAIL-OPEN.
|
|
4
|
+
// Each member is a pole for tests/cr1-refusal-on-resolved.test.ts.
|
|
5
|
+
import {
|
|
6
|
+
requireMasterDirect,
|
|
7
|
+
requireNamespaceSometimes,
|
|
8
|
+
requireNonEmpty,
|
|
9
|
+
requireTenantNamespace,
|
|
10
|
+
withOrgScope,
|
|
11
|
+
} from "./lib/auth";
|
|
12
|
+
|
|
13
|
+
// ─── helpers, product-shaped ─────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
/** ACTION side (okfBundleNode.ts:assertCanExportNamespace): binding through
|
|
16
|
+
* ctx.runQuery(internal.…resolveOrgScopeForAction), refusal through a
|
|
17
|
+
* TRANSITIVE value refuser. */
|
|
18
|
+
async function assertCanExportNamespace(
|
|
19
|
+
ctx: ActionCtx,
|
|
20
|
+
namespace: string,
|
|
21
|
+
door: string,
|
|
22
|
+
): Promise<void> {
|
|
23
|
+
if (namespace.includes("..")) {
|
|
24
|
+
throw new Error(`OKF_NAMESPACE_INVALID: "${namespace}"`);
|
|
25
|
+
}
|
|
26
|
+
const scope = await ctx.runQuery(
|
|
27
|
+
internal.lib.auth.resolveOrgScopeForAction,
|
|
28
|
+
{},
|
|
29
|
+
);
|
|
30
|
+
requireTenantNamespace(scope, namespace, door);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** okfBundleNode.ts:assertCanImport — reaches the gate one call deeper. */
|
|
34
|
+
async function assertCanImport(
|
|
35
|
+
ctx: ActionCtx,
|
|
36
|
+
namespace: string,
|
|
37
|
+
): Promise<void> {
|
|
38
|
+
await assertCanExportNamespace(ctx, namespace, "doors:importBundle");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** V8 side (okfBundleDurable.ts:assertCanExportNamespaceV8): binding through
|
|
42
|
+
* withOrgScope, refusal through the same TRANSITIVE value refuser. */
|
|
43
|
+
async function assertCanExportNamespaceV8(
|
|
44
|
+
ctx: MutationCtx,
|
|
45
|
+
namespace: string,
|
|
46
|
+
door: string,
|
|
47
|
+
): Promise<void> {
|
|
48
|
+
const scope = await withOrgScope(ctx, { refuseWithoutThrow: true });
|
|
49
|
+
requireTenantNamespace(scope, namespace, door);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** binding through withOrgScope, refusal through a DIRECT (one-level) refuser. */
|
|
53
|
+
async function assertMasterDirect(
|
|
54
|
+
ctx: MutationCtx,
|
|
55
|
+
door: string,
|
|
56
|
+
): Promise<void> {
|
|
57
|
+
const scope = await withOrgScope(ctx);
|
|
58
|
+
requireMasterDirect(scope, door);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** NEGATIVE 1 — same resolution, result IGNORED: the refuser is handed the
|
|
62
|
+
* namespace, never the resolved scope. */
|
|
63
|
+
async function assertIgnored(
|
|
64
|
+
ctx: ActionCtx,
|
|
65
|
+
namespace: string,
|
|
66
|
+
door: string,
|
|
67
|
+
): Promise<void> {
|
|
68
|
+
// biome-ignore lint/correctness/noUnusedVariables: the UNUSED binding IS the pole.
|
|
69
|
+
const scope = await ctx.runQuery(
|
|
70
|
+
internal.lib.auth.resolveOrgScopeForAction,
|
|
71
|
+
{},
|
|
72
|
+
);
|
|
73
|
+
requireNonEmpty(namespace, door);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** NEGATIVE 2 — the old okfBundleNode.ts:assertCanValidate shape: the
|
|
77
|
+
* absent-identity branch is a bare `return;`, whatever follows it. */
|
|
78
|
+
async function assertCanValidateOld(
|
|
79
|
+
ctx: ActionCtx,
|
|
80
|
+
namespace: string,
|
|
81
|
+
door: string,
|
|
82
|
+
): Promise<void> {
|
|
83
|
+
const identity = await ctx.auth.getUserIdentity();
|
|
84
|
+
if (identity === null || identity === undefined) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const scope = await ctx.runQuery(
|
|
88
|
+
internal.lib.auth.resolveOrgScopeForAction,
|
|
89
|
+
{},
|
|
90
|
+
);
|
|
91
|
+
requireTenantNamespace(scope, namespace, door);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** NEGATIVE 3 — the refuser proceeds silently on a caller-supplied value. */
|
|
95
|
+
async function assertSometimes(
|
|
96
|
+
ctx: MutationCtx,
|
|
97
|
+
namespace: string,
|
|
98
|
+
door: string,
|
|
99
|
+
): Promise<void> {
|
|
100
|
+
const scope = await withOrgScope(ctx);
|
|
101
|
+
requireNamespaceSometimes(scope, namespace, door);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const readRows = internalQuery({
|
|
105
|
+
args: { namespace: v.string() },
|
|
106
|
+
handler: async (ctx, args) => {
|
|
107
|
+
return await ctx.db
|
|
108
|
+
.query("rows")
|
|
109
|
+
.withIndex("by_namespace", (q) => q.eq("namespace", args.namespace))
|
|
110
|
+
.collect();
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ─── POSITIVE — RESOLVES ─────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
export const exportBundle = action({
|
|
117
|
+
args: { namespace: v.string() },
|
|
118
|
+
handler: async (ctx, args) => {
|
|
119
|
+
await assertCanExportNamespace(ctx, args.namespace, "doors:exportBundle");
|
|
120
|
+
return await ctx.runQuery(internal.doors.readRows, {
|
|
121
|
+
namespace: args.namespace,
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export const importBundle = action({
|
|
127
|
+
args: { namespace: v.string() },
|
|
128
|
+
handler: async (ctx, args) => {
|
|
129
|
+
await assertCanImport(ctx, args.namespace);
|
|
130
|
+
return await ctx.runQuery(internal.doors.readRows, {
|
|
131
|
+
namespace: args.namespace,
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
export const startExport = mutation({
|
|
137
|
+
args: { namespace: v.string() },
|
|
138
|
+
handler: async (ctx, args) => {
|
|
139
|
+
await assertCanExportNamespaceV8(ctx, args.namespace, "doors:startExport");
|
|
140
|
+
return await ctx.db.insert("jobs", { namespace: args.namespace });
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
export const directDoor = mutation({
|
|
145
|
+
args: { namespace: v.string() },
|
|
146
|
+
handler: async (ctx, args) => {
|
|
147
|
+
await assertMasterDirect(ctx, "doors:directDoor");
|
|
148
|
+
return await ctx.db.insert("jobs", { namespace: args.namespace });
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// ─── NEGATIVE — FAIL-OPEN ────────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
export const ignoredDoor = action({
|
|
155
|
+
args: { namespace: v.string() },
|
|
156
|
+
handler: async (ctx, args) => {
|
|
157
|
+
await assertIgnored(ctx, args.namespace, "doors:ignoredDoor");
|
|
158
|
+
return await ctx.runQuery(internal.doors.readRows, {
|
|
159
|
+
namespace: args.namespace,
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
export const validateDoor = action({
|
|
165
|
+
args: { namespace: v.string() },
|
|
166
|
+
handler: async (ctx, args) => {
|
|
167
|
+
await assertCanValidateOld(ctx, args.namespace, "doors:validateDoor");
|
|
168
|
+
return await ctx.runQuery(internal.doors.readRows, {
|
|
169
|
+
namespace: args.namespace,
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export const sometimesDoor = mutation({
|
|
175
|
+
args: { namespace: v.string() },
|
|
176
|
+
handler: async (ctx, args) => {
|
|
177
|
+
await assertSometimes(ctx, args.namespace, "doors:sometimesDoor");
|
|
178
|
+
return await ctx.db.insert("jobs", { namespace: args.namespace });
|
|
179
|
+
},
|
|
180
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// CR-1 fixture — the RESOLVER and REFUSER helpers, shaped after vantage-peers
|
|
2
|
+
// 58ed649 `convex/lib/auth.ts` (withOrgScope, requireResolvedCaller,
|
|
3
|
+
// isNamespaceAllowedForScope, requireTenantNamespace, resolveOrgScopeForAction).
|
|
4
|
+
// Each helper below is a pole for tests/cr1-refusal-on-resolved.test.ts. Do not
|
|
5
|
+
// "tidy" it: a line that looks redundant is a discriminator.
|
|
6
|
+
|
|
7
|
+
/** RESOLVER (not a gate): an absent identity returns an anonymous scope. */
|
|
8
|
+
export async function withOrgScope(ctx: Ctx, opts?: Opts): Promise<Scope> {
|
|
9
|
+
const identity = await ctx.auth.getUserIdentity();
|
|
10
|
+
if (identity === null || identity === undefined) {
|
|
11
|
+
return { isMaster: false, orgSlug: null, anonymous: true, refused: true };
|
|
12
|
+
}
|
|
13
|
+
const row = await ctx.db
|
|
14
|
+
.query("client_org_mapping")
|
|
15
|
+
.withIndex("by_clerk_slug", (q) => q.eq("clerkSlug", identity.org_slug))
|
|
16
|
+
.unique();
|
|
17
|
+
if (row === null || opts?.refuseWithoutThrow) {
|
|
18
|
+
return { isMaster: false, orgSlug: null, anonymous: false, refused: true };
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
isMaster: false,
|
|
22
|
+
orgSlug: row.orgSlug,
|
|
23
|
+
anonymous: false,
|
|
24
|
+
refused: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** VALUE REFUSER, direct: refuses an anonymous scope by raising. */
|
|
29
|
+
export function requireResolvedCaller(
|
|
30
|
+
scope: Pick<Scope, "isMaster" | "orgSlug" | "anonymous" | "refused">,
|
|
31
|
+
registration: string,
|
|
32
|
+
opts?: { masterOnly?: boolean },
|
|
33
|
+
): void {
|
|
34
|
+
if (scope.isMaster) return;
|
|
35
|
+
if (scope.anonymous) {
|
|
36
|
+
throw new ConvexError(
|
|
37
|
+
`RBAC_DENIED: no credential presented to "${registration}"`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
if (opts?.masterOnly) {
|
|
41
|
+
throw new ConvexError(
|
|
42
|
+
`RBAC_DENIED: "${registration}" admits the fleet master only`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** a PREDICATE on the resolved scope — returns a boolean, refuses nothing. */
|
|
48
|
+
export function isNamespaceAllowedForScope(
|
|
49
|
+
scope: Pick<Scope, "isMaster" | "orgSlug">,
|
|
50
|
+
namespace: string,
|
|
51
|
+
): boolean {
|
|
52
|
+
if (scope.isMaster) return true;
|
|
53
|
+
if (scope.orgSlug === null) return false;
|
|
54
|
+
return namespace.startsWith(`team/${scope.orgSlug}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** VALUE REFUSER, TRANSITIVE: no throw of its own — it allows on a test of the
|
|
58
|
+
* RESOLVED scope and otherwise hands that scope to requireResolvedCaller. */
|
|
59
|
+
export function requireTenantNamespace(
|
|
60
|
+
scope: Pick<Scope, "isMaster" | "orgSlug" | "anonymous" | "refused">,
|
|
61
|
+
namespace: string,
|
|
62
|
+
door: string,
|
|
63
|
+
): void {
|
|
64
|
+
if (isNamespaceAllowedForScope(scope, namespace)) return;
|
|
65
|
+
requireResolvedCaller(scope, door, { masterOnly: true });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** VALUE REFUSER, direct, one level: throws on a test of the resolved scope. */
|
|
69
|
+
export function requireMasterDirect(scope: Scope, door: string): void {
|
|
70
|
+
if (!scope.isMaster) {
|
|
71
|
+
throw new ConvexError(
|
|
72
|
+
`RBAC_DENIED: "${door}" admits the fleet master only`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** NOT a refuser of `scope`: it PROCEEDS on a test of a caller-supplied argument
|
|
78
|
+
* before any test of the resolved value — every principal, none included, whose
|
|
79
|
+
* namespace starts `public/` is waved through. */
|
|
80
|
+
export function requireNamespaceSometimes(
|
|
81
|
+
scope: Pick<Scope, "isMaster" | "orgSlug" | "anonymous" | "refused">,
|
|
82
|
+
namespace: string,
|
|
83
|
+
door: string,
|
|
84
|
+
): void {
|
|
85
|
+
if (namespace.startsWith("public/")) return;
|
|
86
|
+
requireResolvedCaller(scope, door, { masterOnly: true });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** a refuser of its OWN argument (a namespace), never of a principal. */
|
|
90
|
+
export function requireNonEmpty(namespace: string, door: string): void {
|
|
91
|
+
if (namespace.length === 0) {
|
|
92
|
+
throw new Error(`OKF_NAMESPACE_INVALID at "${door}"`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** the ONE way an action resolves its caller — reached as
|
|
97
|
+
* `internal.lib.auth.resolveOrgScopeForAction`, never by bare name. */
|
|
98
|
+
export const resolveOrgScopeForAction = internalQuery({
|
|
99
|
+
args: {},
|
|
100
|
+
handler: async (ctx) => {
|
|
101
|
+
const scope = await withOrgScope(ctx, { refuseWithoutThrow: true });
|
|
102
|
+
return scope;
|
|
103
|
+
},
|
|
104
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// verified token here is forwarded verbatim to Convex as `clerkJwt` below,
|
|
2
|
+
// and Convex's own auth.config already requires aud === "convex", so binding
|
|
3
|
+
// the same value here (Critical Rule 14 element 5: aud + iss binding) closes
|
|
4
|
+
// the cross-tenant/cross-resource replay gap without rejecting any token a
|
|
5
|
+
// correctly-configured Clerk "convex" JWT template mints.
|
|
6
|
+
const CLERK_JWT_AUDIENCE = process.env.CLERK_JWT_AUDIENCE ?? "convex";
|
|
7
|
+
|
|
8
|
+
// Lazy singleton — createRemoteJWKSet caches JWKS in-process (10-min TTL).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
* that DOES require the fallback).
|
|
2
|
+
*/
|
|
3
|
+
async function tryVerifyClerkJwt(token: string): Promise<ClerkJwtResult> {
|
|
4
|
+
try {
|
|
5
|
+
const { payload } = await jwtVerify(token, clerkJwks(), {
|
|
6
|
+
issuer: CLERK_DOMAIN,
|
|
7
|
+
audience: CLERK_JWT_AUDIENCE,
|
|
8
|
+
});
|
|
9
|
+
// Verification succeeded — this IS the caller's own Clerk identity.
|
|
10
|
+
// `sub`/`exp` absence here would be a session-token shape violation
|
|
11
|
+
// (not the org concern this function types), so it is still
|
|
12
|
+
// "not-clerk" (try next layer) rather than "no-org".
|
|
13
|
+
const sub = payload.sub;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
outil,table,crud,writer_tier,writer_gate,write_doors
|
|
2
|
+
import_okf_bundle,_storage+briefingNotes+memories+tasks,CREATE,org-member,orgResolver,okfBundleNode:importOkfBundle=orgResolver
|
|
3
|
+
store_document_chunked,_storage+kbUploads+memories,UPSERT,org-member,orgResolver,kb:storeDocumentChunked=orgResolver
|
|
4
|
+
delete_recurring_task,,DELETE,master,masterOnly,recurringTasks:remove=masterOnly
|
|
5
|
+
pause_recurring_task,,UPDATE,master,masterOnly,recurringTasks:pause=masterOnly
|
|
6
|
+
resume_recurring_task,,UPDATE,master,masterOnly,recurringTasks:resume=masterOnly
|
|
7
|
+
soft_delete_memory,,UPDATE,org-member,orgResolver,memories:softDeleteMemory=orgResolver
|
|
8
|
+
create_bu,businessUnits,CREATE,org-member,orgResolver,businessUnits:create=orgResolver
|
|
9
|
+
delete_bu,businessUnits,DELETE,master,masterOnly,businessUnits:remove=masterOnly
|
|
10
|
+
update_bu,businessUnits,UPDATE,org-member,orgResolver,businessUnits:update=orgResolver
|
|
11
|
+
update_task,client_org_mapping+messageReceipts+messages+missions+oauth_access_tokens+taskClosureConfig+tasks,UPSERT,org-member,orgResolver,tasks:update=orgResolver
|
|
12
|
+
send_message,client_org_mapping+messageReceipts+messages+profiles,CREATE,org-member,orgResolver,messages:sendMessage=orgResolver
|
|
13
|
+
update_recurring_task,client_org_mapping+oauth_access_tokens,UPDATE,org-member,orgResolver,recurringTasks:update=orgResolver
|
|
14
|
+
create_recurring_task,client_org_mapping+oauth_access_tokens+recurringTasks,CREATE,org-member,orgResolver,recurringTasks:create=orgResolver
|
|
15
|
+
create_task,client_org_mapping+oauth_access_tokens+tasks,CREATE,org-member,orgResolver,tasks:create=orgResolver
|
|
16
|
+
write_diary,diary,UPSERT,org-member,orgResolver,diary:write=orgResolver
|
|
17
|
+
add_fix_attempt,fixAttempts+fixPatterns,UPSERT,master,masterOnly,fixPatterns:addAttempt=masterOnly
|
|
18
|
+
create_fix_pattern,fixPatterns,CREATE,master,masterOnly,fixPatterns:create=masterOnly
|
|
19
|
+
link_issue_to_pattern,fixPatterns,UPDATE,master,masterOnly,fixPatterns:linkIssue=masterOnly
|
|
20
|
+
validate_fix,fixPatterns,UPDATE,master,masterOnly,fixPatterns:validate=masterOnly
|
|
21
|
+
complete_task,fixPatterns+githubRepoMapping+issues+messageReceipts+messages+taskClosureConfig+tasks,UPSERT,org-member,orgResolver,tasks:complete=orgResolver
|
|
22
|
+
add_repo_mapping,githubRepoMapping,UPSERT,master,masterOnly,githubRepoMapping:add=masterOnly
|
|
23
|
+
remove_repo_mapping,githubRepoMapping,DELETE,master,masterOnly,githubRepoMapping:remove=masterOnly
|
|
24
|
+
link_commit_to_issue,issues,UPDATE,master,masterOnly,issues:linkCommit=masterOnly
|
|
25
|
+
update_issue_status,issues,TRANSITION,master,masterOnly,issues:updateStatus=masterOnly
|
|
26
|
+
verify_issue,issues,TRANSITION,master,masterOnly,issues:verify=masterOnly
|
|
27
|
+
accept_mandate,mandates,TRANSITION,master,masterOnly,mandates:accept=masterOnly
|
|
28
|
+
create_mandate,mandates,CREATE,master,masterOnly,mandates:create=masterOnly
|
|
29
|
+
settle_mandate,mandates,TRANSITION,master,masterOnly,mandates:settle=masterOnly
|
|
30
|
+
update_mandate,mandates+tasks,UPDATE,master,masterOnly,mandates:update=masterOnly
|
|
31
|
+
soft_delete_document,memories,UPDATE,org-member,orgResolver,kb:softDeleteDocument=orgResolver
|
|
32
|
+
store_episode,memories,CREATE,org-member,orgResolver,episodes:storeEpisode=orgResolver
|
|
33
|
+
store_memory,memories,UPSERT,org-member,orgResolver,memories:storeMemory=orgResolver
|
|
34
|
+
mark_as_read,messageReceipts,UPDATE,org-member,orgResolver,messages:markAsRead=orgResolver
|
|
35
|
+
delete_message,messageReceipts+messages,DELETE,org-member,orgResolver,messages:deleteMessage=orgResolver
|
|
36
|
+
add_task_dependency,messageReceipts+messages+missions+taskClosureConfig+tasks,UPSERT,org-member,orgResolver,tasks:update=orgResolver
|
|
37
|
+
block_task,messageReceipts+messages+missions+taskClosureConfig+tasks,UPSERT,org-member,orgResolver,tasks:blockTask=orgResolver; tasks:update=orgResolver
|
|
38
|
+
fail_task,messageReceipts+messages+tasks,UPSERT,org-member,orgResolver,tasks:failTask=orgResolver
|
|
39
|
+
create_mission,missions,CREATE,org-member,orgResolver,missions:create=orgResolver
|
|
40
|
+
update_mission,missions,UPDATE,org-member,orgResolver,missions:update=orgResolver
|
|
41
|
+
update_mission_status,missions,TRANSITION,org-member,orgResolver,missions:updateStatus=orgResolver
|
|
42
|
+
soft_delete_mission_template,missionTemplates,UPDATE,master,masterOnly,missionTemplates:softDelete=masterOnly
|
|
43
|
+
update_mission_template,missionTemplates,UPSERT,master,masterOnly,missionTemplates:upsert=masterOnly
|
|
44
|
+
instantiate_template_into_mission,missionTemplates+missions+tasks,UPSERT,org-member,orgResolver,missionTemplates:instantiateTemplateIntoMission=orgResolver
|
|
45
|
+
add_deployment,monitoredDeployments,UPSERT,master,masterOnly,errorMonitor:addDeployment=masterOnly
|
|
46
|
+
remove_deployment,monitoredDeployments,UPDATE,master,masterOnly,errorMonitor:removeDeployment=masterOnly
|
|
47
|
+
set_summary,profiles,UPSERT,master,masterOnly,profiles:updateDynamic=masterOnly
|
|
48
|
+
update_profile,profiles,UPSERT,master,masterOnly,profiles:upsertProfile=masterOnly
|
|
49
|
+
bulk_complete_tasks,taskClosureConfig+tasks,TRANSITION,org-member,orgResolver,tasks:bulkComplete=orgResolver
|
|
50
|
+
correct_task_segment,taskClosureConfig+tasks,UPDATE,org-member,orgResolver,tasks:correctSegment=orgResolver
|
|
51
|
+
checkout_task,tasks,TRANSITION,org-member,orgResolver,tasks:checkout=orgResolver
|
|
52
|
+
delete_task,tasks,DELETE,org-member,orgResolver,tasks:deleteTask=orgResolver
|
|
53
|
+
pause_task,tasks,TRANSITION,org-member,orgResolver,tasks:pause=orgResolver
|
|
54
|
+
resume_task,tasks,TRANSITION,org-member,orgResolver,tasks:resume=orgResolver
|
|
55
|
+
start_task,tasks,UPDATE,org-member,orgResolver,tasks:start=orgResolver
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vantageos/backend-doctor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A conformance instrument that measures the VantagePeers backend against the pinned backend standard. The THIRD doctor built ON the @vantageos/mcp-doctor engine — never a third engine. It consumes runDoctor/renderTable and adds only detectors.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "tsc",
|
|
19
|
+
"build": "tsc && node scripts/stamp-build.mjs",
|
|
20
20
|
"coverage": "tsx src/coverage-cli.ts",
|
|
21
21
|
"doctor": "tsx src/cli.ts",
|
|
22
22
|
"test": "vitest run",
|