feat: the closed-source rule, and the board

Christian, 2026-10-29: 'Closed source software, you have no idea. And then all
we have is reputation. So you kind of start with one arm or two arms tied
behind your back.'

That is now arithmetic instead of an opinion.

- assessment.source_available: 1 = we can read the code, 0 = we cannot.
- Closed source cannot exceed 5 on ANY dimension without tier-1 or tier-2
  evidence of kind 'capture' or 'filing'. Reputation is tier 3, and tier 3 is
  not a measurement. The build fails if a closed-source score breaks the rule.
- Verifiability still caps at 3 with no reproducible build.

Practical ceiling for closed source: 86/100 in theory, if every dimension is
backed by a capture or a court filing. In practice it is a fight for a C.

- product.priority puts a human's ask ahead of a crawler's discovery.
- v_backlog orders by priority, then measured usage.
- migrate(): the database authors itself, so it must survive its own schema
  changes. Add columns, drop views, let schema.sql recreate them. Never drop
  and rebuild, which would destroy the self-authored roster.

On the board: Slack (closed, capped) and Kino (closed, capped, founders call
2026-10-30 17:00). Neither is scored. Neither gets a number until it has
evidence.
This commit is contained in:
CLU 2026-10-29 15:23:31 -05:00
parent d433a0e75e
commit 76e3e6c0f2
7 changed files with 182 additions and 44 deletions

View file

@ -57,6 +57,7 @@ const VENDORS = {
netflix: ['Netflix, Inc.', 'public', 'US', 'subscription'],
'nextcloud-gmbh': ['Nextcloud GmbH', 'private', 'DE', 'subscription'],
'signal-foundation': ['Signal Technology Foundation', 'nonprofit', 'US', 'none'],
'kino-ai': ['Kino AI', 'private', 'US', 'subscription'],
// discovered products land here until a human or agent resolves the owner
unknown: ['Unknown vendor', 'unknown', 'unknown', 'unknown'],
};
@ -90,6 +91,10 @@ async function build({ fresh = false } = {}) {
const db = new DatabaseSync(DB_PATH);
db.exec('PRAGMA foreign_keys = ON');
db.exec(readFileSync(join(HERE, 'schema.sql'), 'utf8'));
migrate(db);
// second pass: migrate drops the views so this recreates them with the current
// definitions. Views cannot be altered, only replaced.
db.exec(readFileSync(join(HERE, 'schema.sql'), 'utf8'));
// vendors
const insVendor = db.prepare(`INSERT OR REPLACE INTO vendor
@ -127,6 +132,23 @@ async function build({ fresh = false } = {}) {
return { migrated, seeds };
}
// ---------------------------------------------------------------- migrate
// The database authors itself, so it must survive its own schema changes.
// Never drop and rebuild: add the column, drop the views, let schema.sql recreate.
function migrate(db) {
const cols = (t) => db.prepare(`PRAGMA table_info(${t})`).all().map((c) => c.name);
if (!cols('product').includes('priority')) {
db.exec('ALTER TABLE product ADD COLUMN priority INTEGER NOT NULL DEFAULT 0');
}
if (!cols('assessment').includes('source_available')) {
db.exec('ALTER TABLE assessment ADD COLUMN source_available INTEGER NOT NULL DEFAULT 1');
}
for (const v of ['v_backlog', 'v_coverage', 'v_product_score']) {
db.exec(`DROP VIEW IF EXISTS ${v}`);
}
}
// ---------------------------------------------------------------- verify
function verify() {
const db = new DatabaseSync(DB_PATH, { readOnly: true });
@ -167,6 +189,20 @@ function verify() {
const v = db.prepare("SELECT value FROM score WHERE assessment_id = ? AND dimension_id = 'verifiability'").get(a.id)?.value;
if (a.reproducible_build === 0) ok(v <= 3, `${a.id}: no reproducible build but verifiability ${v} > 3`);
if (a.reproducible_build === 1) ok(v <= 6, `${a.id}: experimental reproducible build but verifiability ${v} > 6`);
// Closed source cannot exceed 5 on anything without independent evidence.
// Reputation is tier 3. Tier 3 is not a measurement.
if (a.source_available === 0) {
const above = db.prepare('SELECT * FROM score WHERE assessment_id = ? AND value > 5').all(a.id);
for (const s of above) {
const independent = db.prepare(`
SELECT COUNT(*) AS n FROM evidence
WHERE assessment_id = ? AND dimension_id = ?
AND tier <= 2 AND kind IN ('capture','filing')`).get(a.id, s.dimension_id).n;
ok(independent > 0,
`${a.id}/${s.dimension_id}: closed source scored ${s.value} > 5 with no capture or court filing to back it`);
}
}
}
const scores = db.prepare('SELECT * FROM v_product_score').all();

View file

@ -43,6 +43,8 @@ CREATE TABLE IF NOT EXISTS product (
boss INTEGER NOT NULL DEFAULT 0 CHECK (boss IN (0,1)),
art_slot TEXT,
monthly_cost REAL,
-- priority > 0 puts a product on the board even before anything discovers it
priority INTEGER NOT NULL DEFAULT 0,
notes TEXT,
UNIQUE(id, platform)
);
@ -65,6 +67,9 @@ CREATE TABLE IF NOT EXISTS assessment (
method_version TEXT NOT NULL,
-- 0 = none, 1 = available but experimental/unverified, 2 = verified
reproducible_build INTEGER NOT NULL DEFAULT 0 CHECK (reproducible_build IN (0,1,2)),
-- 1 = we can read the code. 0 = closed. Closed source cannot exceed 5 on any
-- dimension unless independent evidence (a capture or a court filing) says so.
source_available INTEGER NOT NULL DEFAULT 1 CHECK (source_available IN (0,1)),
weighted_total REAL NOT NULL CHECK (weighted_total BETWEEN 0 AND 100),
grade TEXT NOT NULL,
weakest_dimension TEXT NOT NULL REFERENCES dimension(id),
@ -180,17 +185,20 @@ FROM product p
LEFT JOIN assessment a ON a.product_id = p.id
AND a.assessed_on = (SELECT MAX(assessed_on) FROM assessment WHERE product_id = p.id);
-- What to assess next, ordered by how much the thing is actually used.
-- What to assess next. Anything a human put on the board outranks anything a
-- crawler found, and within each tier usage decides.
CREATE VIEW IF NOT EXISTS v_backlog AS
SELECT
p.id AS product_id,
p.name,
p.platform,
p.category_id,
MAX(d.usage_signal) AS usage,
p.priority AS priority,
COALESCE(MAX(d.usage_signal), 0) AS usage,
GROUP_CONCAT(DISTINCT d.source) AS found_via
FROM product p
JOIN discovery d ON d.product_id = p.id
LEFT JOIN discovery d ON d.product_id = p.id
WHERE NOT EXISTS (SELECT 1 FROM assessment a WHERE a.product_id = p.id)
AND (d.id IS NOT NULL OR p.priority > 0)
GROUP BY p.id
ORDER BY usage DESC;
ORDER BY p.priority DESC, usage DESC;

View file

@ -0,0 +1,28 @@
-- =====================================================================
-- 0002 — the board, 2026-10-29
-- Products a human put on the queue. priority > 0 outranks anything a crawler found.
--
-- Neither of these has an assessment yet, and neither gets a number until it
-- has evidence. Slack is closed source, so when it is assessed it will be capped
-- at 5 on every dimension that has no capture or filing behind it.
-- =====================================================================
UPDATE product
SET priority = 10,
notes = 'Queued 2026-10-29 by Christian for the Big Tech Report. Closed source, so verifiability caps at 3 and no dimension may exceed 5 without independent capture or court filing. Score is reputation, not measurement.'
WHERE id = 'slack';
INSERT OR IGNORE INTO product
(id, vendor_id, name, category_id, platform, source_url, license,
sovereign, boss, art_slot, monthly_cost, priority, notes)
VALUES
('kino-ai', 'kino-ai', 'Kino', 'video', 'web', 'https://kino.ai', NULL,
0, 0, NULL, NULL, 10,
'Queued 2026-10-29. YC S23, four people, browser-native editor and AI media manager. Christian signed up same day and asked founders for WebDAV / Nextcloud compatibility. Closed source.');
INSERT OR IGNORE INTO discovery
(product_id, source, source_url, usage_signal, usage_metric, observed_at, raw)
VALUES
('kino-ai', 'manual', 'https://www.ycombinator.com/companies/kino-ai', NULL, 'queued_by_operator',
'2026-10-29T15:22:00-05:00',
'{"batch":"S23","founders":["Wesley Block","Luke Igel"],"note":"formerly local-first desktop logging tool; now browser-native editor"}');

View file

@ -1,5 +1,5 @@
{
"generated_at": "2026-10-29T18:23:54.071Z",
"generated_at": "2026-10-29T20:23:11.576Z",
"method_version": "btr-0.1",
"dimensions": [
{
@ -2634,6 +2634,28 @@
"headline": null,
"assessed_on": null
},
{
"id": "kino-ai",
"name": "Kino",
"platform": "web",
"category_id": "video",
"vendor_id": "kino-ai",
"sovereign": 0,
"boss": 0,
"art_slot": null,
"monthly_cost": null,
"vendor": "Kino AI",
"entity_type": "private",
"jurisdiction": "US",
"business_model": "subscription",
"weighted_total": null,
"grade": null,
"policy": null,
"infra": null,
"weakest_dimension": null,
"headline": null,
"assessed_on": null
},
{
"id": "teams",
"name": "Microsoft Teams",
@ -2829,7 +2851,7 @@
],
"evidence": [
{
"id": 8,
"id": 15,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "local_data_exposure",
"claim": "Attachments are stored unencrypted on the filesystem; the SQLCipher key is held by the OS keyring.",
@ -2840,7 +2862,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 9,
"id": 16,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Electron media permission defaults to false and audio is denied unless the user has enabled mediaPermissions.",
@ -2851,7 +2873,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 10,
"id": 17,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Zero analytics, tracker or crash-upload dependencies across 224 packages.",
@ -2862,7 +2884,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 11,
"id": 18,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Only two audio capture call sites exist and both are reachable only from an explicit UI action.",
@ -2873,7 +2895,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 12,
"id": 19,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "verifiability",
"claim": "Signal states reproducible builds for macOS and Windows are not available, and the Linux build is experimental.",
@ -2884,7 +2906,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 13,
"id": 20,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "server_retention",
"claim": "Grand jury subpoena response returned two timestamps and nothing else.",
@ -2895,7 +2917,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 14,
"id": 21,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "ownership_jurisdiction",
"claim": "Signal Technology Foundation is a 501(c)(3) with EIN 82-4506840.",
@ -2908,7 +2930,7 @@
],
"findings": [
{
"id": 5,
"id": 9,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "high",
"title": "Received attachments are stored unencrypted on disk",
@ -2917,7 +2939,7 @@
"cve": "CVE-2023-24069"
},
{
"id": 6,
"id": 10,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "medium",
"title": "No verified reproducible build for the Linux package",
@ -2926,7 +2948,7 @@
"cve": null
},
{
"id": 7,
"id": 11,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "medium",
"title": "Local database key is held in the OS keyring",
@ -2935,7 +2957,7 @@
"cve": null
},
{
"id": 8,
"id": 12,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "low",
"title": "Registration requires a phone number",

View file

@ -39,7 +39,7 @@ export interface CatalogDimension {
}
export const catalog = {
"generated_at": "2026-10-29T18:23:54.071Z",
"generated_at": "2026-10-29T20:23:11.576Z",
"method_version": "btr-0.1",
"dimensions": [
{
@ -2674,6 +2674,28 @@ export const catalog = {
"headline": null,
"assessed_on": null
},
{
"id": "kino-ai",
"name": "Kino",
"platform": "web",
"category_id": "video",
"vendor_id": "kino-ai",
"sovereign": 0,
"boss": 0,
"art_slot": null,
"monthly_cost": null,
"vendor": "Kino AI",
"entity_type": "private",
"jurisdiction": "US",
"business_model": "subscription",
"weighted_total": null,
"grade": null,
"policy": null,
"infra": null,
"weakest_dimension": null,
"headline": null,
"assessed_on": null
},
{
"id": "teams",
"name": "Microsoft Teams",
@ -2869,7 +2891,7 @@ export const catalog = {
],
"evidence": [
{
"id": 8,
"id": 15,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "local_data_exposure",
"claim": "Attachments are stored unencrypted on the filesystem; the SQLCipher key is held by the OS keyring.",
@ -2880,7 +2902,7 @@ export const catalog = {
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 9,
"id": 16,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Electron media permission defaults to false and audio is denied unless the user has enabled mediaPermissions.",
@ -2891,7 +2913,7 @@ export const catalog = {
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 10,
"id": 17,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Zero analytics, tracker or crash-upload dependencies across 224 packages.",
@ -2902,7 +2924,7 @@ export const catalog = {
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 11,
"id": 18,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Only two audio capture call sites exist and both are reachable only from an explicit UI action.",
@ -2913,7 +2935,7 @@ export const catalog = {
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 12,
"id": 19,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "verifiability",
"claim": "Signal states reproducible builds for macOS and Windows are not available, and the Linux build is experimental.",
@ -2924,7 +2946,7 @@ export const catalog = {
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 13,
"id": 20,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "server_retention",
"claim": "Grand jury subpoena response returned two timestamps and nothing else.",
@ -2935,7 +2957,7 @@ export const catalog = {
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 14,
"id": 21,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "ownership_jurisdiction",
"claim": "Signal Technology Foundation is a 501(c)(3) with EIN 82-4506840.",
@ -2948,7 +2970,7 @@ export const catalog = {
],
"findings": [
{
"id": 5,
"id": 9,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "high",
"title": "Received attachments are stored unencrypted on disk",
@ -2957,7 +2979,7 @@ export const catalog = {
"cve": "CVE-2023-24069"
},
{
"id": 6,
"id": 10,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "medium",
"title": "No verified reproducible build for the Linux package",
@ -2966,7 +2988,7 @@ export const catalog = {
"cve": null
},
{
"id": 7,
"id": 11,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "medium",
"title": "Local database key is held in the OS keyring",
@ -2975,7 +2997,7 @@ export const catalog = {
"cve": null
},
{
"id": 8,
"id": 12,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "low",
"title": "Registration requires a phone number",

View file

@ -1,5 +1,5 @@
{
"generated_at": "2026-10-29T18:23:54.071Z",
"generated_at": "2026-10-29T20:23:11.576Z",
"method_version": "btr-0.1",
"dimensions": [
{
@ -2634,6 +2634,28 @@
"headline": null,
"assessed_on": null
},
{
"id": "kino-ai",
"name": "Kino",
"platform": "web",
"category_id": "video",
"vendor_id": "kino-ai",
"sovereign": 0,
"boss": 0,
"art_slot": null,
"monthly_cost": null,
"vendor": "Kino AI",
"entity_type": "private",
"jurisdiction": "US",
"business_model": "subscription",
"weighted_total": null,
"grade": null,
"policy": null,
"infra": null,
"weakest_dimension": null,
"headline": null,
"assessed_on": null
},
{
"id": "teams",
"name": "Microsoft Teams",
@ -2829,7 +2851,7 @@
],
"evidence": [
{
"id": 8,
"id": 15,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "local_data_exposure",
"claim": "Attachments are stored unencrypted on the filesystem; the SQLCipher key is held by the OS keyring.",
@ -2840,7 +2862,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 9,
"id": 16,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Electron media permission defaults to false and audio is denied unless the user has enabled mediaPermissions.",
@ -2851,7 +2873,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 10,
"id": 17,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Zero analytics, tracker or crash-upload dependencies across 224 packages.",
@ -2862,7 +2884,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 11,
"id": 18,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "telemetry_egress",
"claim": "Only two audio capture call sites exist and both are reachable only from an explicit UI action.",
@ -2873,7 +2895,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 12,
"id": 19,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "verifiability",
"claim": "Signal states reproducible builds for macOS and Windows are not available, and the Linux build is experimental.",
@ -2884,7 +2906,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 13,
"id": 20,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "server_retention",
"claim": "Grand jury subpoena response returned two timestamps and nothing else.",
@ -2895,7 +2917,7 @@
"observed_at": "2026-10-29T13:13:56-05:00"
},
{
"id": 14,
"id": 21,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"dimension_id": "ownership_jurisdiction",
"claim": "Signal Technology Foundation is a 501(c)(3) with EIN 82-4506840.",
@ -2908,7 +2930,7 @@
],
"findings": [
{
"id": 5,
"id": 9,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "high",
"title": "Received attachments are stored unencrypted on disk",
@ -2917,7 +2939,7 @@
"cve": "CVE-2023-24069"
},
{
"id": 6,
"id": 10,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "medium",
"title": "No verified reproducible build for the Linux package",
@ -2926,7 +2948,7 @@
"cve": null
},
{
"id": 7,
"id": 11,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "medium",
"title": "Local database key is held in the OS keyring",
@ -2935,7 +2957,7 @@
"cve": null
},
{
"id": 8,
"id": 12,
"assessment_id": "A-2026-10-29-SIGNAL-DESKTOP",
"severity": "low",
"title": "Registration requires a phone number",

View file

@ -1,10 +1,10 @@
{
"digest": "5aadd709b394ab19e13a65aa21fb5182cb736f53e2b60c175abebb8dd11f1d8a",
"digest": "37a9774dc7569335d8135828aa5b97d294e26252185b0b31dc4a8f4dadde59db",
"algorithm": "sha256",
"file": "catalog.json",
"byte_length": 79846,
"rebuilt_at": "2026-10-29T18:23:54.074Z",
"byte_length": 80389,
"rebuilt_at": "2026-10-29T20:23:11.578Z",
"method_version": "btr-0.1",
"products": 122,
"products": 123,
"assessed": 1
}