@rigour-labs/core 6.2.5 → 6.3.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 +2 -0
- package/dist/discovery-signals.d.ts +27 -0
- package/dist/discovery-signals.js +96 -0
- package/dist/discovery.d.ts +1 -2
- package/dist/discovery.js +36 -49
- package/dist/discovery.test.js +84 -71
- package/dist/gates/deep-analysis.d.ts +2 -0
- package/dist/gates/deep-analysis.js +5 -1
- package/dist/gates/deep-intent.d.ts +3 -0
- package/dist/gates/deep-intent.js +57 -0
- package/dist/gates/deep-intent.test.d.ts +1 -0
- package/dist/gates/deep-intent.test.js +51 -0
- package/dist/gates/deep-runner.js +1 -0
- package/dist/gates/deprecated-apis-ast.d.ts +8 -0
- package/dist/gates/deprecated-apis-ast.js +25 -0
- package/dist/gates/deprecated-apis-rules-node.js +2 -8
- package/dist/gates/deprecated-apis.js +5 -1
- package/dist/gates/deprecated-apis.test.js +30 -0
- package/dist/gates/frontend-secret-exposure.js +5 -1
- package/dist/gates/frontend-secret-exposure.test.js +20 -0
- package/dist/gates/hallucinated-imports/framework-modules.d.ts +14 -0
- package/dist/gates/hallucinated-imports/framework-modules.js +75 -0
- package/dist/gates/hallucinated-imports/index.js +14 -6
- package/dist/gates/hallucinated-imports/js-resolver.d.ts +16 -12
- package/dist/gates/hallucinated-imports/js-resolver.js +65 -153
- package/dist/gates/hallucinated-imports/ts-path-target.js +16 -0
- package/dist/gates/hallucinated-imports/tsconfig-paths.d.ts +16 -0
- package/dist/gates/hallucinated-imports/tsconfig-paths.js +120 -0
- package/dist/gates/hallucinated-imports-sveltekit.test.d.ts +1 -0
- package/dist/gates/hallucinated-imports-sveltekit.test.js +108 -0
- package/dist/gates/runner.js +5 -0
- package/dist/gates/semantic-bugs.d.ts +23 -0
- package/dist/gates/semantic-bugs.js +48 -0
- package/dist/gates/semantic-bugs.test.d.ts +1 -0
- package/dist/gates/semantic-bugs.test.js +70 -0
- package/dist/gates/side-effect-analysis/index.js +11 -1
- package/dist/gates/side-effect-analysis.test.d.ts +1 -0
- package/dist/gates/side-effect-analysis.test.js +162 -0
- package/dist/gates/side-effect-helpers/pattern-detection.js +35 -7
- package/dist/gates/side-effect-helpers/resource-tracking.js +17 -10
- package/dist/gates/side-effect-helpers/scope-analysis.d.ts +6 -0
- package/dist/gates/side-effect-helpers/scope-analysis.js +20 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -1
- package/dist/inference/sidecar-provider.js +12 -1
- package/dist/inference/types.d.ts +2 -0
- package/dist/semantic/ast.d.ts +29 -0
- package/dist/semantic/ast.js +122 -0
- package/dist/semantic/benchmark.d.ts +16 -0
- package/dist/semantic/benchmark.js +31 -0
- package/dist/semantic/benchmark.test.d.ts +1 -0
- package/dist/semantic/benchmark.test.js +18 -0
- package/dist/semantic/engine.d.ts +8 -0
- package/dist/semantic/engine.js +45 -0
- package/dist/semantic/intent/benchmark.d.ts +31 -0
- package/dist/semantic/intent/benchmark.js +74 -0
- package/dist/semantic/intent/intent-check.d.ts +43 -0
- package/dist/semantic/intent/intent-check.js +72 -0
- package/dist/semantic/intent/intent.test.d.ts +1 -0
- package/dist/semantic/intent/intent.test.js +46 -0
- package/dist/semantic/intent/parallel-reads.d.ts +23 -0
- package/dist/semantic/intent/parallel-reads.js +59 -0
- package/dist/semantic/learn/benchmark.d.ts +20 -0
- package/dist/semantic/learn/benchmark.js +71 -0
- package/dist/semantic/learn/compile.d.ts +4 -0
- package/dist/semantic/learn/compile.js +56 -0
- package/dist/semantic/learn/conditions.d.ts +22 -0
- package/dist/semantic/learn/conditions.js +93 -0
- package/dist/semantic/learn/extract.d.ts +30 -0
- package/dist/semantic/learn/extract.js +122 -0
- package/dist/semantic/learn/git-trees.d.ts +8 -0
- package/dist/semantic/learn/git-trees.js +32 -0
- package/dist/semantic/learn/identity.d.ts +18 -0
- package/dist/semantic/learn/identity.js +97 -0
- package/dist/semantic/learn/learn.d.ts +25 -0
- package/dist/semantic/learn/learn.js +109 -0
- package/dist/semantic/learn/learn.test.d.ts +1 -0
- package/dist/semantic/learn/learn.test.js +67 -0
- package/dist/semantic/learn/store.d.ts +4 -0
- package/dist/semantic/learn/store.js +39 -0
- package/dist/semantic/learn/types.d.ts +468 -0
- package/dist/semantic/learn/types.js +55 -0
- package/dist/semantic/origins.d.ts +42 -0
- package/dist/semantic/origins.js +149 -0
- package/dist/semantic/origins.test.d.ts +1 -0
- package/dist/semantic/origins.test.js +77 -0
- package/dist/semantic/program.d.ts +13 -0
- package/dist/semantic/program.js +62 -0
- package/dist/semantic/rules/credential-redirect.d.ts +2 -0
- package/dist/semantic/rules/credential-redirect.js +209 -0
- package/dist/semantic/rules/degraded-response-cached.d.ts +2 -0
- package/dist/semantic/rules/degraded-response-cached.js +271 -0
- package/dist/semantic/rules/in-memory-aggregation.d.ts +2 -0
- package/dist/semantic/rules/in-memory-aggregation.js +179 -0
- package/dist/semantic/summaries.d.ts +18 -0
- package/dist/semantic/summaries.js +33 -0
- package/dist/semantic/types.d.ts +32 -0
- package/dist/semantic/types.js +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +1 -0
- package/dist/storage/team-diagnostics.d.ts +22 -0
- package/dist/storage/team-diagnostics.js +58 -0
- package/dist/storage/team-diagnostics.test.d.ts +1 -0
- package/dist/storage/team-diagnostics.test.js +51 -0
- package/dist/storage/team-schema.d.ts +6 -0
- package/dist/storage/team-schema.js +82 -0
- package/dist/storage/team-store.js +25 -72
- package/dist/templates/universal-config.js +4 -0
- package/dist/types/index.d.ts +56 -0
- package/dist/types/index.js +7 -0
- package/package.json +6 -6
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { diagnoseMissingMembership, explainTeamConnectionError } from './team-diagnostics.js';
|
|
3
|
+
import { TEAM_SCHEMA } from './team-schema.js';
|
|
4
|
+
function pool(rows) {
|
|
5
|
+
return {
|
|
6
|
+
query: async () => {
|
|
7
|
+
if (rows instanceof Error)
|
|
8
|
+
throw rows;
|
|
9
|
+
return { rows, rowCount: rows.length };
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
describe('explainTeamConnectionError', () => {
|
|
14
|
+
it('explains an untrusted certificate chain with the CA fix', () => {
|
|
15
|
+
const message = explainTeamConnectionError(Object.assign(new Error('self-signed certificate in certificate chain'), { code: 'SELF_SIGNED_CERT_IN_CHAIN' }));
|
|
16
|
+
expect(message).toContain('NODE_EXTRA_CA_CERTS');
|
|
17
|
+
expect(message).toContain('sslmode=verify-full');
|
|
18
|
+
});
|
|
19
|
+
it('points a missing schema at init-schema', () => {
|
|
20
|
+
expect(explainTeamConnectionError({ code: '42P01', message: 'relation "rigour.memberships" does not exist' })).toContain('rigour team init-schema');
|
|
21
|
+
});
|
|
22
|
+
it('explains a rejected login and an unreachable host', () => {
|
|
23
|
+
expect(explainTeamConnectionError({ code: '28P01', message: 'password authentication failed' })).toContain('rejected the login');
|
|
24
|
+
expect(explainTeamConnectionError({ code: 'ECONNREFUSED', message: 'connect ECONNREFUSED' })).toContain('Cannot reach');
|
|
25
|
+
});
|
|
26
|
+
it('passes other errors through', () => {
|
|
27
|
+
expect(explainTeamConnectionError(new Error('something else'))).toBe('something else');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe('diagnoseMissingMembership', () => {
|
|
31
|
+
it('names row-level security without a policy as the cause', async () => {
|
|
32
|
+
const message = await diagnoseMissingMembership(pool([{ table_name: 'memberships' }, { table_name: 'meta' }]));
|
|
33
|
+
expect(message).toContain('rigour.memberships and rigour.meta');
|
|
34
|
+
expect(message).toContain('init-schema');
|
|
35
|
+
});
|
|
36
|
+
it('reports a missing membership when nothing hides it', async () => {
|
|
37
|
+
expect(await diagnoseMissingMembership(pool([]))).toContain('no membership');
|
|
38
|
+
});
|
|
39
|
+
it('falls back to the membership message when the catalog cannot be read', async () => {
|
|
40
|
+
expect(await diagnoseMissingMembership(pool(new Error('permission denied')))).toContain('no membership');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('team schema', () => {
|
|
44
|
+
it('protects every team table with row-level security and a read policy', () => {
|
|
45
|
+
for (const table of ['lessons', 'memberships', 'meta']) {
|
|
46
|
+
expect(TEAM_SCHEMA).toContain(`ALTER TABLE rigour.${table} ENABLE ROW LEVEL SECURITY;`);
|
|
47
|
+
}
|
|
48
|
+
expect(TEAM_SCHEMA).toContain('CREATE POLICY memberships_read_own ON rigour.memberships FOR SELECT USING (db_role = current_user);');
|
|
49
|
+
expect(TEAM_SCHEMA).toContain('CREATE POLICY meta_read ON rigour.meta FOR SELECT USING (true);');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL team schema. Idempotent: re-running it on an existing database
|
|
3
|
+
* (`rigour team init-schema`) adds anything missing, including the RLS
|
|
4
|
+
* policies, without touching data.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TEAM_SCHEMA = "\nCREATE SCHEMA IF NOT EXISTS rigour;\nCREATE TABLE IF NOT EXISTS rigour.meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\nCREATE TABLE IF NOT EXISTS rigour.memberships (\n db_role NAME NOT NULL,\n organization_id TEXT NOT NULL,\n team_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n role TEXT NOT NULL CHECK (role IN ('member', 'sme', 'owner')),\n PRIMARY KEY (db_role, team_id)\n);\nCREATE TABLE IF NOT EXISTS rigour.lessons (\n id TEXT PRIMARY KEY,\n organization_id TEXT NOT NULL,\n team_id TEXT NOT NULL,\n repository_id TEXT NOT NULL,\n actor_id TEXT NOT NULL,\n visibility TEXT NOT NULL CHECK (visibility IN ('personal', 'team')),\n state TEXT NOT NULL CHECK (state IN ('candidate', 'validated', 'promoted', 'rejected', 'superseded')),\n kind TEXT NOT NULL,\n subject TEXT NOT NULL,\n evidence_json JSONB NOT NULL,\n confidence DOUBLE PRECISION NOT NULL,\n source TEXT NOT NULL,\n supersedes_id TEXT,\n created_at BIGINT NOT NULL,\n updated_at BIGINT NOT NULL\n);\nALTER TABLE rigour.lessons ENABLE ROW LEVEL SECURITY;\nDROP POLICY IF EXISTS lessons_read ON rigour.lessons;\nCREATE POLICY lessons_read ON rigour.lessons FOR SELECT USING (\n EXISTS (\n SELECT 1 FROM rigour.memberships membership\n WHERE membership.db_role = current_user\n AND membership.organization_id = lessons.organization_id\n AND membership.team_id = lessons.team_id\n AND ((lessons.visibility = 'team' AND lessons.state = 'promoted')\n OR membership.actor_id = lessons.actor_id)\n )\n);\nDROP POLICY IF EXISTS lessons_write ON rigour.lessons;\nCREATE POLICY lessons_write ON rigour.lessons FOR ALL USING (\n EXISTS (\n SELECT 1 FROM rigour.memberships membership\n WHERE membership.db_role = current_user\n AND membership.organization_id = lessons.organization_id\n AND membership.team_id = lessons.team_id\n AND membership.actor_id = lessons.actor_id\n AND (lessons.visibility = 'personal' OR membership.role IN ('sme', 'owner'))\n )\n) WITH CHECK (\n EXISTS (\n SELECT 1 FROM rigour.memberships membership\n WHERE membership.db_role = current_user\n AND membership.organization_id = lessons.organization_id\n AND membership.team_id = lessons.team_id\n AND membership.actor_id = lessons.actor_id\n AND (lessons.visibility = 'personal' OR membership.role IN ('sme', 'owner'))\n )\n);\n-- Row-level security on every team table. A host (for example Supabase's\n-- security advisor) may enable RLS on its own; without a policy each member\n-- login would then see no rows at all. Members read only their own\n-- membership rows (the lessons policies read memberships the same way), and\n-- meta holds only the schema version.\nALTER TABLE rigour.memberships ENABLE ROW LEVEL SECURITY;\nDROP POLICY IF EXISTS memberships_read_own ON rigour.memberships;\nCREATE POLICY memberships_read_own ON rigour.memberships FOR SELECT USING (db_role = current_user);\nALTER TABLE rigour.meta ENABLE ROW LEVEL SECURITY;\nDROP POLICY IF EXISTS meta_read ON rigour.meta;\nCREATE POLICY meta_read ON rigour.meta FOR SELECT USING (true);\nINSERT INTO rigour.meta (key, value) VALUES ('schema_version', '1')\nON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;\n";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL team schema. Idempotent: re-running it on an existing database
|
|
3
|
+
* (`rigour team init-schema`) adds anything missing, including the RLS
|
|
4
|
+
* policies, without touching data.
|
|
5
|
+
*/
|
|
6
|
+
export const TEAM_SCHEMA = `
|
|
7
|
+
CREATE SCHEMA IF NOT EXISTS rigour;
|
|
8
|
+
CREATE TABLE IF NOT EXISTS rigour.meta (
|
|
9
|
+
key TEXT PRIMARY KEY,
|
|
10
|
+
value TEXT NOT NULL
|
|
11
|
+
);
|
|
12
|
+
CREATE TABLE IF NOT EXISTS rigour.memberships (
|
|
13
|
+
db_role NAME NOT NULL,
|
|
14
|
+
organization_id TEXT NOT NULL,
|
|
15
|
+
team_id TEXT NOT NULL,
|
|
16
|
+
actor_id TEXT NOT NULL,
|
|
17
|
+
role TEXT NOT NULL CHECK (role IN ('member', 'sme', 'owner')),
|
|
18
|
+
PRIMARY KEY (db_role, team_id)
|
|
19
|
+
);
|
|
20
|
+
CREATE TABLE IF NOT EXISTS rigour.lessons (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
organization_id TEXT NOT NULL,
|
|
23
|
+
team_id TEXT NOT NULL,
|
|
24
|
+
repository_id TEXT NOT NULL,
|
|
25
|
+
actor_id TEXT NOT NULL,
|
|
26
|
+
visibility TEXT NOT NULL CHECK (visibility IN ('personal', 'team')),
|
|
27
|
+
state TEXT NOT NULL CHECK (state IN ('candidate', 'validated', 'promoted', 'rejected', 'superseded')),
|
|
28
|
+
kind TEXT NOT NULL,
|
|
29
|
+
subject TEXT NOT NULL,
|
|
30
|
+
evidence_json JSONB NOT NULL,
|
|
31
|
+
confidence DOUBLE PRECISION NOT NULL,
|
|
32
|
+
source TEXT NOT NULL,
|
|
33
|
+
supersedes_id TEXT,
|
|
34
|
+
created_at BIGINT NOT NULL,
|
|
35
|
+
updated_at BIGINT NOT NULL
|
|
36
|
+
);
|
|
37
|
+
ALTER TABLE rigour.lessons ENABLE ROW LEVEL SECURITY;
|
|
38
|
+
DROP POLICY IF EXISTS lessons_read ON rigour.lessons;
|
|
39
|
+
CREATE POLICY lessons_read ON rigour.lessons FOR SELECT USING (
|
|
40
|
+
EXISTS (
|
|
41
|
+
SELECT 1 FROM rigour.memberships membership
|
|
42
|
+
WHERE membership.db_role = current_user
|
|
43
|
+
AND membership.organization_id = lessons.organization_id
|
|
44
|
+
AND membership.team_id = lessons.team_id
|
|
45
|
+
AND ((lessons.visibility = 'team' AND lessons.state = 'promoted')
|
|
46
|
+
OR membership.actor_id = lessons.actor_id)
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
DROP POLICY IF EXISTS lessons_write ON rigour.lessons;
|
|
50
|
+
CREATE POLICY lessons_write ON rigour.lessons FOR ALL USING (
|
|
51
|
+
EXISTS (
|
|
52
|
+
SELECT 1 FROM rigour.memberships membership
|
|
53
|
+
WHERE membership.db_role = current_user
|
|
54
|
+
AND membership.organization_id = lessons.organization_id
|
|
55
|
+
AND membership.team_id = lessons.team_id
|
|
56
|
+
AND membership.actor_id = lessons.actor_id
|
|
57
|
+
AND (lessons.visibility = 'personal' OR membership.role IN ('sme', 'owner'))
|
|
58
|
+
)
|
|
59
|
+
) WITH CHECK (
|
|
60
|
+
EXISTS (
|
|
61
|
+
SELECT 1 FROM rigour.memberships membership
|
|
62
|
+
WHERE membership.db_role = current_user
|
|
63
|
+
AND membership.organization_id = lessons.organization_id
|
|
64
|
+
AND membership.team_id = lessons.team_id
|
|
65
|
+
AND membership.actor_id = lessons.actor_id
|
|
66
|
+
AND (lessons.visibility = 'personal' OR membership.role IN ('sme', 'owner'))
|
|
67
|
+
)
|
|
68
|
+
);
|
|
69
|
+
-- Row-level security on every team table. A host (for example Supabase's
|
|
70
|
+
-- security advisor) may enable RLS on its own; without a policy each member
|
|
71
|
+
-- login would then see no rows at all. Members read only their own
|
|
72
|
+
-- membership rows (the lessons policies read memberships the same way), and
|
|
73
|
+
-- meta holds only the schema version.
|
|
74
|
+
ALTER TABLE rigour.memberships ENABLE ROW LEVEL SECURITY;
|
|
75
|
+
DROP POLICY IF EXISTS memberships_read_own ON rigour.memberships;
|
|
76
|
+
CREATE POLICY memberships_read_own ON rigour.memberships FOR SELECT USING (db_role = current_user);
|
|
77
|
+
ALTER TABLE rigour.meta ENABLE ROW LEVEL SECURITY;
|
|
78
|
+
DROP POLICY IF EXISTS meta_read ON rigour.meta;
|
|
79
|
+
CREATE POLICY meta_read ON rigour.meta FOR SELECT USING (true);
|
|
80
|
+
INSERT INTO rigour.meta (key, value) VALUES ('schema_version', '1')
|
|
81
|
+
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
|
|
82
|
+
`;
|
|
@@ -3,6 +3,8 @@ import os from 'os';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { openDatabase } from './db.js';
|
|
5
5
|
import { decryptLocalPayload, encryptLocalPayload } from './local-encryption.js';
|
|
6
|
+
import { TEAM_SCHEMA } from './team-schema.js';
|
|
7
|
+
import { diagnoseMissingMembership, explainTeamConnectionError } from './team-diagnostics.js';
|
|
6
8
|
import { TEAM_VECTOR_SCHEMA, backfillConfiguredTeamEmbeddings, getTeamSemanticHealth, searchConfiguredTeamKnowledge, upsertTeamLessonEmbedding, } from './team-vector-store.js';
|
|
7
9
|
const DEFAULT_SEMANTIC = {
|
|
8
10
|
provider: 'pgvector',
|
|
@@ -84,72 +86,6 @@ async function queuedChanges() {
|
|
|
84
86
|
await db.close();
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
|
-
const TEAM_SCHEMA = `
|
|
88
|
-
CREATE SCHEMA IF NOT EXISTS rigour;
|
|
89
|
-
CREATE TABLE IF NOT EXISTS rigour.meta (
|
|
90
|
-
key TEXT PRIMARY KEY,
|
|
91
|
-
value TEXT NOT NULL
|
|
92
|
-
);
|
|
93
|
-
CREATE TABLE IF NOT EXISTS rigour.memberships (
|
|
94
|
-
db_role NAME NOT NULL,
|
|
95
|
-
organization_id TEXT NOT NULL,
|
|
96
|
-
team_id TEXT NOT NULL,
|
|
97
|
-
actor_id TEXT NOT NULL,
|
|
98
|
-
role TEXT NOT NULL CHECK (role IN ('member', 'sme', 'owner')),
|
|
99
|
-
PRIMARY KEY (db_role, team_id)
|
|
100
|
-
);
|
|
101
|
-
CREATE TABLE IF NOT EXISTS rigour.lessons (
|
|
102
|
-
id TEXT PRIMARY KEY,
|
|
103
|
-
organization_id TEXT NOT NULL,
|
|
104
|
-
team_id TEXT NOT NULL,
|
|
105
|
-
repository_id TEXT NOT NULL,
|
|
106
|
-
actor_id TEXT NOT NULL,
|
|
107
|
-
visibility TEXT NOT NULL CHECK (visibility IN ('personal', 'team')),
|
|
108
|
-
state TEXT NOT NULL CHECK (state IN ('candidate', 'validated', 'promoted', 'rejected', 'superseded')),
|
|
109
|
-
kind TEXT NOT NULL,
|
|
110
|
-
subject TEXT NOT NULL,
|
|
111
|
-
evidence_json JSONB NOT NULL,
|
|
112
|
-
confidence DOUBLE PRECISION NOT NULL,
|
|
113
|
-
source TEXT NOT NULL,
|
|
114
|
-
supersedes_id TEXT,
|
|
115
|
-
created_at BIGINT NOT NULL,
|
|
116
|
-
updated_at BIGINT NOT NULL
|
|
117
|
-
);
|
|
118
|
-
ALTER TABLE rigour.lessons ENABLE ROW LEVEL SECURITY;
|
|
119
|
-
DROP POLICY IF EXISTS lessons_read ON rigour.lessons;
|
|
120
|
-
CREATE POLICY lessons_read ON rigour.lessons FOR SELECT USING (
|
|
121
|
-
EXISTS (
|
|
122
|
-
SELECT 1 FROM rigour.memberships membership
|
|
123
|
-
WHERE membership.db_role = current_user
|
|
124
|
-
AND membership.organization_id = lessons.organization_id
|
|
125
|
-
AND membership.team_id = lessons.team_id
|
|
126
|
-
AND ((lessons.visibility = 'team' AND lessons.state = 'promoted')
|
|
127
|
-
OR membership.actor_id = lessons.actor_id)
|
|
128
|
-
)
|
|
129
|
-
);
|
|
130
|
-
DROP POLICY IF EXISTS lessons_write ON rigour.lessons;
|
|
131
|
-
CREATE POLICY lessons_write ON rigour.lessons FOR ALL USING (
|
|
132
|
-
EXISTS (
|
|
133
|
-
SELECT 1 FROM rigour.memberships membership
|
|
134
|
-
WHERE membership.db_role = current_user
|
|
135
|
-
AND membership.organization_id = lessons.organization_id
|
|
136
|
-
AND membership.team_id = lessons.team_id
|
|
137
|
-
AND membership.actor_id = lessons.actor_id
|
|
138
|
-
AND (lessons.visibility = 'personal' OR membership.role IN ('sme', 'owner'))
|
|
139
|
-
)
|
|
140
|
-
) WITH CHECK (
|
|
141
|
-
EXISTS (
|
|
142
|
-
SELECT 1 FROM rigour.memberships membership
|
|
143
|
-
WHERE membership.db_role = current_user
|
|
144
|
-
AND membership.organization_id = lessons.organization_id
|
|
145
|
-
AND membership.team_id = lessons.team_id
|
|
146
|
-
AND membership.actor_id = lessons.actor_id
|
|
147
|
-
AND (lessons.visibility = 'personal' OR membership.role IN ('sme', 'owner'))
|
|
148
|
-
)
|
|
149
|
-
);
|
|
150
|
-
INSERT INTO rigour.meta (key, value) VALUES ('schema_version', '1')
|
|
151
|
-
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
|
|
152
|
-
`;
|
|
153
89
|
export async function initializeTeamSchema(databaseUrl, options = {}) {
|
|
154
90
|
validateTeamDatabaseUrl(databaseUrl);
|
|
155
91
|
const { Pool } = await loadPg();
|
|
@@ -171,7 +107,7 @@ export async function getTeamModeStatus() {
|
|
|
171
107
|
}
|
|
172
108
|
try {
|
|
173
109
|
const result = await doctorTeamConnection(config);
|
|
174
|
-
return result;
|
|
110
|
+
return result.connectivity === 'offline' ? { ...result, message: `Offline — changes queued. ${result.message}` } : result;
|
|
175
111
|
}
|
|
176
112
|
catch (error) {
|
|
177
113
|
return {
|
|
@@ -190,7 +126,21 @@ export async function doctorTeamConnection(config) {
|
|
|
190
126
|
if (!resolved?.databaseUrl) {
|
|
191
127
|
return { mode: 'local', connectivity: 'local', queuedChanges: await queuedChanges(), message: 'Team mode is not configured.' };
|
|
192
128
|
}
|
|
193
|
-
|
|
129
|
+
const offline = async (message) => ({
|
|
130
|
+
mode: 'team',
|
|
131
|
+
connectivity: 'offline',
|
|
132
|
+
organizationId: resolved.organizationId,
|
|
133
|
+
teamId: resolved.teamId,
|
|
134
|
+
actorId: resolved.actorId,
|
|
135
|
+
queuedChanges: await queuedChanges(),
|
|
136
|
+
message,
|
|
137
|
+
});
|
|
138
|
+
try {
|
|
139
|
+
validateTeamDatabaseUrl(resolved.databaseUrl);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
return offline(explainTeamConnectionError(error));
|
|
143
|
+
}
|
|
194
144
|
const { Pool } = await loadPg();
|
|
195
145
|
const pool = new Pool({ connectionString: resolved.databaseUrl });
|
|
196
146
|
try {
|
|
@@ -200,10 +150,10 @@ export async function doctorTeamConnection(config) {
|
|
|
200
150
|
FROM rigour.memberships
|
|
201
151
|
WHERE db_role = current_user AND team_id = $1 AND actor_id = $2 AND organization_id = $3`, [resolved.teamId, resolved.actorId, resolved.organizationId]);
|
|
202
152
|
if (result.rowCount !== 1)
|
|
203
|
-
|
|
153
|
+
return offline(await diagnoseMissingMembership(pool));
|
|
204
154
|
const schemaVersion = Number(result.rows[0].schema_version);
|
|
205
155
|
if (schemaVersion !== 1)
|
|
206
|
-
|
|
156
|
+
return offline(`Incompatible team schema version ${schemaVersion}; expected 1.`);
|
|
207
157
|
const semantic = resolved.semantic ? await getTeamSemanticHealth(pool, resolved) : undefined;
|
|
208
158
|
return {
|
|
209
159
|
mode: 'team',
|
|
@@ -219,8 +169,11 @@ export async function doctorTeamConnection(config) {
|
|
|
219
169
|
message: 'PostgreSQL team mode is healthy.',
|
|
220
170
|
};
|
|
221
171
|
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return offline(explainTeamConnectionError(error));
|
|
174
|
+
}
|
|
222
175
|
finally {
|
|
223
|
-
await pool.end();
|
|
176
|
+
await pool.end().catch(() => undefined);
|
|
224
177
|
}
|
|
225
178
|
}
|
|
226
179
|
export async function syncTeamOutbox(options = {}) {
|
|
@@ -243,7 +196,7 @@ export async function syncTeamOutbox(options = {}) {
|
|
|
243
196
|
WHERE db_role = current_user AND team_id = $1
|
|
244
197
|
AND actor_id = $2 AND organization_id = $3`, [config.teamId, config.actorId, config.organizationId]);
|
|
245
198
|
if (membership.rowCount !== 1)
|
|
246
|
-
throw new Error(
|
|
199
|
+
throw new Error(await diagnoseMissingMembership(pool));
|
|
247
200
|
for (const item of pending) {
|
|
248
201
|
const lesson = await decryptLocalPayload(item.payload_json);
|
|
249
202
|
try {
|
|
@@ -234,6 +234,9 @@ export const UNIVERSAL_CONFIG = {
|
|
|
234
234
|
track_branches: true,
|
|
235
235
|
track_returns: true,
|
|
236
236
|
},
|
|
237
|
+
semantic_bugs: {
|
|
238
|
+
enabled: false,
|
|
239
|
+
},
|
|
237
240
|
side_effect_analysis: {
|
|
238
241
|
enabled: true,
|
|
239
242
|
check_unbounded_timers: true,
|
|
@@ -252,6 +255,7 @@ export const UNIVERSAL_CONFIG = {
|
|
|
252
255
|
provider: 'local',
|
|
253
256
|
threads: 4,
|
|
254
257
|
temperature: 0.1,
|
|
258
|
+
intent_checks: false,
|
|
255
259
|
checks: {
|
|
256
260
|
solid: true,
|
|
257
261
|
dry: true,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -495,6 +495,16 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
495
495
|
custom_patterns?: string[] | undefined;
|
|
496
496
|
audit_log?: boolean | undefined;
|
|
497
497
|
}>>>;
|
|
498
|
+
semantic_bugs: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
499
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
500
|
+
rules: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
501
|
+
}, "strip", z.ZodTypeAny, {
|
|
502
|
+
enabled: boolean;
|
|
503
|
+
rules?: string[] | undefined;
|
|
504
|
+
}, {
|
|
505
|
+
enabled?: boolean | undefined;
|
|
506
|
+
rules?: string[] | undefined;
|
|
507
|
+
}>>>;
|
|
498
508
|
side_effect_analysis: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
499
509
|
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
500
510
|
check_unbounded_timers: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -576,6 +586,7 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
576
586
|
max_tokens: z.ZodOptional<z.ZodNumber>;
|
|
577
587
|
temperature: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
578
588
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
589
|
+
intent_checks: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
579
590
|
checks: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
580
591
|
solid: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
581
592
|
dry: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -610,6 +621,7 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
610
621
|
provider: string;
|
|
611
622
|
threads: number;
|
|
612
623
|
temperature: number;
|
|
624
|
+
intent_checks: boolean;
|
|
613
625
|
checks: {
|
|
614
626
|
architecture: boolean;
|
|
615
627
|
test_quality: boolean;
|
|
@@ -638,6 +650,7 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
638
650
|
max_tokens?: number | undefined;
|
|
639
651
|
temperature?: number | undefined;
|
|
640
652
|
timeout_ms?: number | undefined;
|
|
653
|
+
intent_checks?: boolean | undefined;
|
|
641
654
|
checks?: {
|
|
642
655
|
architecture?: boolean | undefined;
|
|
643
656
|
test_quality?: boolean | undefined;
|
|
@@ -656,6 +669,7 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
656
669
|
provider: string;
|
|
657
670
|
threads: number;
|
|
658
671
|
temperature: number;
|
|
672
|
+
intent_checks: boolean;
|
|
659
673
|
checks: {
|
|
660
674
|
architecture: boolean;
|
|
661
675
|
test_quality: boolean;
|
|
@@ -852,6 +866,10 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
852
866
|
custom_patterns: string[];
|
|
853
867
|
audit_log: boolean;
|
|
854
868
|
};
|
|
869
|
+
semantic_bugs: {
|
|
870
|
+
enabled: boolean;
|
|
871
|
+
rules?: string[] | undefined;
|
|
872
|
+
};
|
|
855
873
|
side_effect_analysis: {
|
|
856
874
|
enabled: boolean;
|
|
857
875
|
ignore_patterns: string[];
|
|
@@ -890,6 +908,7 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
890
908
|
max_tokens?: number | undefined;
|
|
891
909
|
temperature?: number | undefined;
|
|
892
910
|
timeout_ms?: number | undefined;
|
|
911
|
+
intent_checks?: boolean | undefined;
|
|
893
912
|
checks?: {
|
|
894
913
|
architecture?: boolean | undefined;
|
|
895
914
|
test_quality?: boolean | undefined;
|
|
@@ -1080,6 +1099,10 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
1080
1099
|
custom_patterns?: string[] | undefined;
|
|
1081
1100
|
audit_log?: boolean | undefined;
|
|
1082
1101
|
} | undefined;
|
|
1102
|
+
semantic_bugs?: {
|
|
1103
|
+
enabled?: boolean | undefined;
|
|
1104
|
+
rules?: string[] | undefined;
|
|
1105
|
+
} | undefined;
|
|
1083
1106
|
side_effect_analysis?: {
|
|
1084
1107
|
enabled?: boolean | undefined;
|
|
1085
1108
|
ignore_patterns?: string[] | undefined;
|
|
@@ -1661,6 +1684,16 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
1661
1684
|
custom_patterns?: string[] | undefined;
|
|
1662
1685
|
audit_log?: boolean | undefined;
|
|
1663
1686
|
}>>>;
|
|
1687
|
+
semantic_bugs: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1688
|
+
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1689
|
+
rules: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1690
|
+
}, "strip", z.ZodTypeAny, {
|
|
1691
|
+
enabled: boolean;
|
|
1692
|
+
rules?: string[] | undefined;
|
|
1693
|
+
}, {
|
|
1694
|
+
enabled?: boolean | undefined;
|
|
1695
|
+
rules?: string[] | undefined;
|
|
1696
|
+
}>>>;
|
|
1664
1697
|
side_effect_analysis: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1665
1698
|
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1666
1699
|
check_unbounded_timers: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -1742,6 +1775,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
1742
1775
|
max_tokens: z.ZodOptional<z.ZodNumber>;
|
|
1743
1776
|
temperature: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
1744
1777
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
1778
|
+
intent_checks: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1745
1779
|
checks: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1746
1780
|
solid: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1747
1781
|
dry: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -1776,6 +1810,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
1776
1810
|
provider: string;
|
|
1777
1811
|
threads: number;
|
|
1778
1812
|
temperature: number;
|
|
1813
|
+
intent_checks: boolean;
|
|
1779
1814
|
checks: {
|
|
1780
1815
|
architecture: boolean;
|
|
1781
1816
|
test_quality: boolean;
|
|
@@ -1804,6 +1839,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
1804
1839
|
max_tokens?: number | undefined;
|
|
1805
1840
|
temperature?: number | undefined;
|
|
1806
1841
|
timeout_ms?: number | undefined;
|
|
1842
|
+
intent_checks?: boolean | undefined;
|
|
1807
1843
|
checks?: {
|
|
1808
1844
|
architecture?: boolean | undefined;
|
|
1809
1845
|
test_quality?: boolean | undefined;
|
|
@@ -1822,6 +1858,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
1822
1858
|
provider: string;
|
|
1823
1859
|
threads: number;
|
|
1824
1860
|
temperature: number;
|
|
1861
|
+
intent_checks: boolean;
|
|
1825
1862
|
checks: {
|
|
1826
1863
|
architecture: boolean;
|
|
1827
1864
|
test_quality: boolean;
|
|
@@ -2018,6 +2055,10 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2018
2055
|
custom_patterns: string[];
|
|
2019
2056
|
audit_log: boolean;
|
|
2020
2057
|
};
|
|
2058
|
+
semantic_bugs: {
|
|
2059
|
+
enabled: boolean;
|
|
2060
|
+
rules?: string[] | undefined;
|
|
2061
|
+
};
|
|
2021
2062
|
side_effect_analysis: {
|
|
2022
2063
|
enabled: boolean;
|
|
2023
2064
|
ignore_patterns: string[];
|
|
@@ -2056,6 +2097,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2056
2097
|
max_tokens?: number | undefined;
|
|
2057
2098
|
temperature?: number | undefined;
|
|
2058
2099
|
timeout_ms?: number | undefined;
|
|
2100
|
+
intent_checks?: boolean | undefined;
|
|
2059
2101
|
checks?: {
|
|
2060
2102
|
architecture?: boolean | undefined;
|
|
2061
2103
|
test_quality?: boolean | undefined;
|
|
@@ -2246,6 +2288,10 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2246
2288
|
custom_patterns?: string[] | undefined;
|
|
2247
2289
|
audit_log?: boolean | undefined;
|
|
2248
2290
|
} | undefined;
|
|
2291
|
+
semantic_bugs?: {
|
|
2292
|
+
enabled?: boolean | undefined;
|
|
2293
|
+
rules?: string[] | undefined;
|
|
2294
|
+
} | undefined;
|
|
2249
2295
|
side_effect_analysis?: {
|
|
2250
2296
|
enabled?: boolean | undefined;
|
|
2251
2297
|
ignore_patterns?: string[] | undefined;
|
|
@@ -2320,6 +2366,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2320
2366
|
provider: string;
|
|
2321
2367
|
threads: number;
|
|
2322
2368
|
temperature: number;
|
|
2369
|
+
intent_checks: boolean;
|
|
2323
2370
|
checks: {
|
|
2324
2371
|
architecture: boolean;
|
|
2325
2372
|
test_quality: boolean;
|
|
@@ -2516,6 +2563,10 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2516
2563
|
custom_patterns: string[];
|
|
2517
2564
|
audit_log: boolean;
|
|
2518
2565
|
};
|
|
2566
|
+
semantic_bugs: {
|
|
2567
|
+
enabled: boolean;
|
|
2568
|
+
rules?: string[] | undefined;
|
|
2569
|
+
};
|
|
2519
2570
|
side_effect_analysis: {
|
|
2520
2571
|
enabled: boolean;
|
|
2521
2572
|
ignore_patterns: string[];
|
|
@@ -2580,6 +2631,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2580
2631
|
max_tokens?: number | undefined;
|
|
2581
2632
|
temperature?: number | undefined;
|
|
2582
2633
|
timeout_ms?: number | undefined;
|
|
2634
|
+
intent_checks?: boolean | undefined;
|
|
2583
2635
|
checks?: {
|
|
2584
2636
|
architecture?: boolean | undefined;
|
|
2585
2637
|
test_quality?: boolean | undefined;
|
|
@@ -2770,6 +2822,10 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
2770
2822
|
custom_patterns?: string[] | undefined;
|
|
2771
2823
|
audit_log?: boolean | undefined;
|
|
2772
2824
|
} | undefined;
|
|
2825
|
+
semantic_bugs?: {
|
|
2826
|
+
enabled?: boolean | undefined;
|
|
2827
|
+
rules?: string[] | undefined;
|
|
2828
|
+
} | undefined;
|
|
2773
2829
|
side_effect_analysis?: {
|
|
2774
2830
|
enabled?: boolean | undefined;
|
|
2775
2831
|
ignore_patterns?: string[] | undefined;
|
package/dist/types/index.js
CHANGED
|
@@ -266,6 +266,10 @@ export const GatesSchema = z.object({
|
|
|
266
266
|
audit_log: z.boolean().optional().default(true),
|
|
267
267
|
}).optional().default({}),
|
|
268
268
|
// v4.3+ Side-Effect Safety Analysis
|
|
269
|
+
semantic_bugs: z.object({
|
|
270
|
+
enabled: z.boolean().optional().default(false),
|
|
271
|
+
rules: z.array(z.string()).optional(),
|
|
272
|
+
}).optional().default({}),
|
|
269
273
|
side_effect_analysis: z.object({
|
|
270
274
|
enabled: z.boolean().optional().default(true),
|
|
271
275
|
check_unbounded_timers: z.boolean().optional().default(true),
|
|
@@ -306,6 +310,9 @@ export const GatesSchema = z.object({
|
|
|
306
310
|
max_tokens: z.number().optional(), // default per provider: local 1024, cloud 4096
|
|
307
311
|
temperature: z.number().optional().default(0.1),
|
|
308
312
|
timeout_ms: z.number().optional(), // per inference call; default per provider: local 60s, cloud 120s
|
|
313
|
+
// Intent questions at engine-proven sites (optional-read-no-fallback) in scoped reviews.
|
|
314
|
+
// Off: the stock local models failed the zero-false-finding bar (docs/DEEP_ANALYSIS.md).
|
|
315
|
+
intent_checks: z.boolean().optional().default(false),
|
|
309
316
|
checks: z.object({
|
|
310
317
|
solid: z.boolean().optional().default(true),
|
|
311
318
|
dry: z.boolean().optional().default(true),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigour-labs/core",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "AI-native quality gate engine with local Bayesian learning. AST analysis, drift detection, Fix Packet generation, and agent self-healing across TypeScript, JavaScript, Python, Go, Ruby, and C#.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://rigour.run",
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"pg": "^8.16.3",
|
|
68
68
|
"sqlite3": "^5.1.7",
|
|
69
69
|
"openai": "^4.104.0",
|
|
70
|
-
"@rigour-labs/brain-darwin-arm64": "6.
|
|
71
|
-
"@rigour-labs/brain-darwin-x64": "6.
|
|
72
|
-
"@rigour-labs/brain-linux-arm64": "6.
|
|
73
|
-
"@rigour-labs/brain-win-x64": "6.
|
|
74
|
-
"@rigour-labs/brain-linux-x64": "6.
|
|
70
|
+
"@rigour-labs/brain-darwin-arm64": "6.3.0",
|
|
71
|
+
"@rigour-labs/brain-darwin-x64": "6.3.0",
|
|
72
|
+
"@rigour-labs/brain-linux-arm64": "6.3.0",
|
|
73
|
+
"@rigour-labs/brain-win-x64": "6.3.0",
|
|
74
|
+
"@rigour-labs/brain-linux-x64": "6.3.0"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@types/fs-extra": "^11.0.4",
|