@hasna/todos 0.15.6 → 0.15.7

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.
Files changed (40) hide show
  1. package/dist/cli/cloud-router.d.ts.map +1 -1
  2. package/dist/cli/index.js +3011 -1325
  3. package/dist/contracts.js +213 -3
  4. package/dist/db/migrations.d.ts.map +1 -1
  5. package/dist/db/schema.d.ts.map +1 -1
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1950 -26
  9. package/dist/mcp/index.js +2073 -371
  10. package/dist/mcp.js +7 -3
  11. package/dist/project-registration/authority.d.ts +45 -0
  12. package/dist/project-registration/authority.d.ts.map +1 -0
  13. package/dist/project-registration/backend.d.ts +83 -0
  14. package/dist/project-registration/backend.d.ts.map +1 -0
  15. package/dist/project-registration/http.d.ts +24 -0
  16. package/dist/project-registration/http.d.ts.map +1 -0
  17. package/dist/project-registration/index.d.ts +8 -0
  18. package/dist/project-registration/index.d.ts.map +1 -0
  19. package/dist/project-registration/postgres.d.ts +30 -0
  20. package/dist/project-registration/postgres.d.ts.map +1 -0
  21. package/dist/project-registration/schema.d.ts +3 -0
  22. package/dist/project-registration/schema.d.ts.map +1 -0
  23. package/dist/project-registration/sqlite.d.ts +17 -0
  24. package/dist/project-registration/sqlite.d.ts.map +1 -0
  25. package/dist/project-registration/types.d.ts +155 -0
  26. package/dist/project-registration/types.d.ts.map +1 -0
  27. package/dist/project-registration.d.ts +2 -0
  28. package/dist/project-registration.d.ts.map +1 -0
  29. package/dist/project-registration.js +17689 -0
  30. package/dist/registry.d.ts +1 -1
  31. package/dist/registry.d.ts.map +1 -1
  32. package/dist/registry.js +220 -3
  33. package/dist/release-provenance.json +5 -5
  34. package/dist/server/cloud.d.ts +3 -0
  35. package/dist/server/cloud.d.ts.map +1 -1
  36. package/dist/server/index.js +4374 -2672
  37. package/dist/server/v1.d.ts +2 -1
  38. package/dist/server/v1.d.ts.map +1 -1
  39. package/dist/storage.js +206 -0
  40. package/package.json +7 -3
@@ -1,10 +1,11 @@
1
1
  import type { TodosStorageSnapshot } from "../storage/interfaces.js";
2
- import { getCloudPrGroupLedger, getCloudStorageAdapter, getCloudVerifier, ensureCloudSchema } from "./cloud.js";
2
+ import { ensureCloudSchema, getCloudPrGroupLedger, getCloudProjectRegistrationAuthority, getCloudStorageAdapter, getCloudVerifier } from "./cloud.js";
3
3
  export interface V1RequestDependencies {
4
4
  getVerifier?: typeof getCloudVerifier;
5
5
  ensureSchema?: typeof ensureCloudSchema;
6
6
  getStorageAdapter?: typeof getCloudStorageAdapter;
7
7
  getPrGroupLedger?: typeof getCloudPrGroupLedger;
8
+ getProjectRegistrationAuthority?: typeof getCloudProjectRegistrationAuthority;
8
9
  }
9
10
  /**
10
11
  * Coerce an arbitrary request body into a well-formed {@link TodosStorageSnapshot}.
@@ -1 +1 @@
1
- {"version":3,"file":"v1.d.ts","sourceRoot":"","sources":["../../src/server/v1.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAuB,oBAAoB,EAAmD,MAAM,0BAA0B,CAAC;AAC3I,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMhH,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,OAAO,gBAAgB,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,iBAAiB,CAAC;IACxC,iBAAiB,CAAC,EAAE,OAAO,sBAAsB,CAAC;IAClD,gBAAgB,CAAC,EAAE,OAAO,qBAAqB,CAAC;CACjD;AAuSD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB,CAiB1E;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAapE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,YAAY,GAAE,qBAA0B,GACvC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAu6B1B"}
1
+ {"version":3,"file":"v1.d.ts","sourceRoot":"","sources":["../../src/server/v1.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAuB,oBAAoB,EAAmD,MAAM,0BAA0B,CAAC;AAC3I,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oCAAoC,EACpC,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAOpB,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,OAAO,gBAAgB,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,iBAAiB,CAAC;IACxC,iBAAiB,CAAC,EAAE,OAAO,sBAAsB,CAAC;IAClD,gBAAgB,CAAC,EAAE,OAAO,qBAAqB,CAAC;IAChD,+BAA+B,CAAC,EAAE,OAAO,oCAAoC,CAAC;CAC/E;AAuSD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB,CAiB1E;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAapE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,YAAY,GAAE,qBAA0B,GACvC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAk7B1B"}
package/dist/storage.js CHANGED
@@ -459,6 +459,206 @@ var init_types = __esm(() => {
459
459
  };
460
460
  });
461
461
 
462
+ // src/project-registration/schema.ts
463
+ function sqliteTodosProjectRegistrationSchemaSql() {
464
+ return `
465
+ CREATE TABLE IF NOT EXISTS todos_project_registration_receipts (
466
+ receipt_id TEXT PRIMARY KEY,
467
+ authority TEXT NOT NULL CHECK(authority = 'todos'),
468
+ route TEXT NOT NULL,
469
+ package_version TEXT NOT NULL,
470
+ authority_id TEXT NOT NULL,
471
+ tenant_id TEXT NOT NULL,
472
+ corpus_id TEXT NOT NULL,
473
+ operation_id TEXT NOT NULL,
474
+ step_id TEXT NOT NULL,
475
+ resource_kind TEXT NOT NULL CHECK(resource_kind IN ('project', 'task_list')),
476
+ direction TEXT NOT NULL CHECK(direction IN ('forward', 'inverse')),
477
+ target_selector TEXT NOT NULL,
478
+ idempotency_key TEXT NOT NULL,
479
+ request_digest TEXT NOT NULL,
480
+ precondition_digest TEXT NOT NULL,
481
+ normalized_call_digest TEXT NOT NULL,
482
+ outcome TEXT NOT NULL CHECK(outcome IN (
483
+ 'accepted', 'duplicate_of_accepted', 'terminal_nonacceptance'
484
+ )),
485
+ reason TEXT,
486
+ target_id TEXT,
487
+ result_revision TEXT,
488
+ result_digest TEXT,
489
+ duplicate_of_receipt_id TEXT,
490
+ accepted_receipt_id TEXT,
491
+ created_by_operation INTEGER NOT NULL CHECK(created_by_operation IN (0, 1)),
492
+ created_at TEXT NOT NULL
493
+ );
494
+
495
+ CREATE INDEX IF NOT EXISTS idx_todos_project_registration_receipts_lookup
496
+ ON todos_project_registration_receipts (
497
+ authority_id, tenant_id, corpus_id, operation_id, step_id,
498
+ resource_kind, direction, idempotency_key
499
+ );
500
+ CREATE INDEX IF NOT EXISTS idx_todos_project_registration_receipts_step
501
+ ON todos_project_registration_receipts (
502
+ authority_id, tenant_id, corpus_id, operation_id, step_id,
503
+ resource_kind, direction, outcome
504
+ );
505
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_todos_project_registration_receipts_accepted_step
506
+ ON todos_project_registration_receipts (
507
+ authority_id, tenant_id, corpus_id, operation_id, step_id,
508
+ resource_kind, direction
509
+ )
510
+ WHERE outcome = 'accepted';
511
+ CREATE INDEX IF NOT EXISTS idx_todos_project_registration_receipts_target
512
+ ON todos_project_registration_receipts (
513
+ authority_id, tenant_id, corpus_id, resource_kind, target_id
514
+ );
515
+
516
+ CREATE TABLE IF NOT EXISTS todos_project_registration_bindings (
517
+ authority_id TEXT NOT NULL,
518
+ tenant_id TEXT NOT NULL,
519
+ corpus_id TEXT NOT NULL,
520
+ resource_kind TEXT NOT NULL CHECK(resource_kind IN ('project', 'task_list')),
521
+ target_selector TEXT NOT NULL,
522
+ operation_id TEXT NOT NULL,
523
+ step_id TEXT NOT NULL,
524
+ direction TEXT NOT NULL CHECK(direction = 'forward'),
525
+ idempotency_key TEXT NOT NULL,
526
+ request_digest TEXT NOT NULL,
527
+ precondition_digest TEXT NOT NULL,
528
+ normalized_call_digest TEXT NOT NULL,
529
+ state TEXT NOT NULL CHECK(state IN (
530
+ 'pending', 'accepted', 'terminal_nonacceptance', 'removed'
531
+ )),
532
+ target_id TEXT,
533
+ accepted_receipt_id TEXT,
534
+ result_revision TEXT,
535
+ result_digest TEXT,
536
+ removed_receipt_id TEXT,
537
+ created_at TEXT NOT NULL,
538
+ updated_at TEXT NOT NULL,
539
+ PRIMARY KEY(
540
+ authority_id, tenant_id, corpus_id, resource_kind, target_selector
541
+ ),
542
+ UNIQUE(accepted_receipt_id)
543
+ );
544
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_todos_project_registration_binding_target
545
+ ON todos_project_registration_bindings(
546
+ authority_id, tenant_id, corpus_id, resource_kind, target_id
547
+ )
548
+ WHERE target_id IS NOT NULL;
549
+
550
+ CREATE TRIGGER IF NOT EXISTS todos_project_registration_receipts_immutable_update
551
+ BEFORE UPDATE ON todos_project_registration_receipts
552
+ BEGIN
553
+ SELECT RAISE(ABORT, 'todos project registration receipts are immutable');
554
+ END;
555
+
556
+ CREATE TRIGGER IF NOT EXISTS todos_project_registration_receipts_immutable_delete
557
+ BEFORE DELETE ON todos_project_registration_receipts
558
+ BEGIN
559
+ SELECT RAISE(ABORT, 'todos project registration receipts are immutable');
560
+ END;
561
+ `;
562
+ }
563
+ function postgresTodosProjectRegistrationSchemaSql() {
564
+ return [
565
+ `CREATE TABLE IF NOT EXISTS todos_project_registration_receipts (
566
+ receipt_id text PRIMARY KEY,
567
+ authority text NOT NULL CHECK(authority = 'todos'),
568
+ route text NOT NULL,
569
+ package_version text NOT NULL,
570
+ authority_id text NOT NULL,
571
+ tenant_id text NOT NULL,
572
+ corpus_id text NOT NULL,
573
+ operation_id text NOT NULL,
574
+ step_id text NOT NULL,
575
+ resource_kind text NOT NULL CHECK(resource_kind IN ('project', 'task_list')),
576
+ direction text NOT NULL CHECK(direction IN ('forward', 'inverse')),
577
+ target_selector text NOT NULL,
578
+ idempotency_key text NOT NULL,
579
+ request_digest text NOT NULL,
580
+ precondition_digest text NOT NULL,
581
+ normalized_call_digest text NOT NULL,
582
+ outcome text NOT NULL CHECK(outcome IN (
583
+ 'accepted', 'duplicate_of_accepted', 'terminal_nonacceptance'
584
+ )),
585
+ reason text,
586
+ target_id text,
587
+ result_revision text,
588
+ result_digest text,
589
+ duplicate_of_receipt_id text,
590
+ accepted_receipt_id text,
591
+ created_by_operation boolean NOT NULL,
592
+ created_at timestamptz NOT NULL
593
+ )`,
594
+ `CREATE INDEX IF NOT EXISTS todos_project_registration_receipts_lookup_idx
595
+ ON todos_project_registration_receipts (
596
+ authority_id, tenant_id, corpus_id, operation_id, step_id,
597
+ resource_kind, direction, idempotency_key
598
+ )`,
599
+ `CREATE INDEX IF NOT EXISTS todos_project_registration_receipts_step_idx
600
+ ON todos_project_registration_receipts (
601
+ authority_id, tenant_id, corpus_id, operation_id, step_id,
602
+ resource_kind, direction, outcome
603
+ )`,
604
+ `CREATE UNIQUE INDEX IF NOT EXISTS todos_project_registration_receipts_accepted_step_uidx
605
+ ON todos_project_registration_receipts (
606
+ authority_id, tenant_id, corpus_id, operation_id, step_id,
607
+ resource_kind, direction
608
+ )
609
+ WHERE outcome = 'accepted'`,
610
+ `CREATE INDEX IF NOT EXISTS todos_project_registration_receipts_target_idx
611
+ ON todos_project_registration_receipts (
612
+ authority_id, tenant_id, corpus_id, resource_kind, target_id
613
+ )`,
614
+ `CREATE TABLE IF NOT EXISTS todos_project_registration_bindings (
615
+ authority_id text NOT NULL,
616
+ tenant_id text NOT NULL,
617
+ corpus_id text NOT NULL,
618
+ resource_kind text NOT NULL CHECK(resource_kind IN ('project', 'task_list')),
619
+ target_selector text NOT NULL,
620
+ operation_id text NOT NULL,
621
+ step_id text NOT NULL,
622
+ direction text NOT NULL CHECK(direction = 'forward'),
623
+ idempotency_key text NOT NULL,
624
+ request_digest text NOT NULL,
625
+ precondition_digest text NOT NULL,
626
+ normalized_call_digest text NOT NULL,
627
+ state text NOT NULL CHECK(state IN (
628
+ 'pending', 'accepted', 'terminal_nonacceptance', 'removed'
629
+ )),
630
+ target_id text,
631
+ accepted_receipt_id text UNIQUE,
632
+ result_revision text,
633
+ result_digest text,
634
+ removed_receipt_id text,
635
+ created_at timestamptz NOT NULL,
636
+ updated_at timestamptz NOT NULL,
637
+ PRIMARY KEY(
638
+ authority_id, tenant_id, corpus_id, resource_kind, target_selector
639
+ )
640
+ )`,
641
+ `CREATE UNIQUE INDEX IF NOT EXISTS todos_project_registration_binding_target_uidx
642
+ ON todos_project_registration_bindings(
643
+ authority_id, tenant_id, corpus_id, resource_kind, target_id
644
+ )
645
+ WHERE target_id IS NOT NULL`,
646
+ `CREATE OR REPLACE FUNCTION todos_project_registration_receipts_immutable()
647
+ RETURNS trigger
648
+ LANGUAGE plpgsql
649
+ AS $$
650
+ BEGIN
651
+ RAISE EXCEPTION 'todos project registration receipts are immutable';
652
+ END;
653
+ $$`,
654
+ `DROP TRIGGER IF EXISTS todos_project_registration_receipts_immutable
655
+ ON todos_project_registration_receipts`,
656
+ `CREATE TRIGGER todos_project_registration_receipts_immutable
657
+ BEFORE UPDATE OR DELETE ON todos_project_registration_receipts
658
+ FOR EACH ROW EXECUTE FUNCTION todos_project_registration_receipts_immutable()`
659
+ ];
660
+ }
661
+
462
662
  // src/db/migrations.ts
463
663
  var MIGRATIONS;
464
664
  var init_migrations = __esm(() => {
@@ -2064,6 +2264,11 @@ var init_migrations = __esm(() => {
2064
2264
  INSERT OR IGNORE INTO _migrations (id) VALUES (68);
2065
2265
  COMMIT;
2066
2266
  PRAGMA foreign_keys = ON;
2267
+ `,
2268
+ `BEGIN;
2269
+ ${sqliteTodosProjectRegistrationSchemaSql()}
2270
+ INSERT OR IGNORE INTO _migrations (id) VALUES (69);
2271
+ COMMIT;
2067
2272
  `
2068
2273
  ];
2069
2274
  });
@@ -3266,6 +3471,7 @@ function ensureSchema(db) {
3266
3471
  )`);
3267
3472
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_api_keys_prefix ON api_keys(prefix)");
3268
3473
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_api_keys_active ON api_keys(revoked_at, expires_at)");
3474
+ db.exec(sqliteTodosProjectRegistrationSchemaSql());
3269
3475
  ensureTable("pr_groups", `
3270
3476
  CREATE TABLE pr_groups (
3271
3477
  schema_version INTEGER NOT NULL DEFAULT 1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.15.6",
3
+ "version": "0.15.7",
4
4
  "description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -38,6 +38,10 @@
38
38
  "./testing": {
39
39
  "types": "./dist/testing.d.ts",
40
40
  "import": "./dist/testing.js"
41
+ },
42
+ "./project-registration": {
43
+ "types": "./dist/project-registration.d.ts",
44
+ "import": "./dist/project-registration.js"
41
45
  }
42
46
  },
43
47
  "workspaces": [
@@ -50,8 +54,8 @@
50
54
  "README.md"
51
55
  ],
52
56
  "scripts": {
53
- "build": "rm -rf dist dashboard/dist && cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts src/testing.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && tsc --emitDeclarationOnly --outDir dist",
54
- "build:server": "rm -rf dist && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts src/testing.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*'",
57
+ "build": "rm -rf dist dashboard/dist && cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts src/testing.ts src/project-registration.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && tsc --emitDeclarationOnly --outDir dist",
58
+ "build:server": "rm -rf dist && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts src/testing.ts src/project-registration.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*'",
55
59
  "migrate": "bun run src/server/index.ts migrate",
56
60
  "backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
57
61
  "generate:sdk": "bun run scripts/generate-sdk.ts",