@3sln/trove 0.0.11 → 0.0.13

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 (90) hide show
  1. package/README.md +13 -1
  2. package/package.json +2 -1
  3. package/packages/core/src/collections/index.js +71 -10
  4. package/packages/core/src/encryption/keys.js +4 -3
  5. package/packages/core/src/encryption/policy.js +14 -7
  6. package/packages/core/src/encryption/rotation.js +46 -12
  7. package/packages/core/src/errors.js +8 -0
  8. package/packages/core/src/index.js +8 -2
  9. package/packages/core/src/indexers/contribution.js +18 -17
  10. package/packages/core/src/indexing.js +8 -4
  11. package/packages/core/src/issues.js +8 -0
  12. package/packages/core/src/links.js +21 -9
  13. package/packages/core/src/metadata/interface.js +22 -0
  14. package/packages/core/src/metadata/memory.js +15 -0
  15. package/packages/core/src/metadata/sqlite.js +23 -1
  16. package/packages/core/src/plugins/contributions.js +13 -0
  17. package/packages/core/src/rateLimit.js +253 -0
  18. package/packages/core/src/scan.js +44 -16
  19. package/packages/core/src/sidecar/document.js +18 -14
  20. package/packages/core/src/sidecar/index.js +9 -10
  21. package/packages/core/src/sidecar/manager.js +10 -15
  22. package/packages/core/src/uploads.js +40 -15
  23. package/packages/core/src/vfs.js +59 -34
  24. package/packages/plugin-sdk/src/browser.js +155 -0
  25. package/packages/plugin-sdk/src/protocol.js +13 -1
  26. package/packages/server/src/access/externalEvaluation.js +17 -0
  27. package/packages/server/src/adapters/bun.js +1 -2
  28. package/packages/server/src/adapters/node.js +1 -2
  29. package/packages/server/src/engine/index.js +1 -1
  30. package/packages/server/src/engine/providers/access.js +17 -34
  31. package/packages/server/src/engine/providers/core.js +112 -14
  32. package/packages/server/src/index.js +160 -105
  33. package/packages/server/src/mcp/index.js +7 -12
  34. package/packages/server/src/mcp/tools.js +24 -29
  35. package/packages/server/src/router.js +31 -8
  36. package/packages/server/src/routes.js +74 -113
  37. package/packages/server/src/scope.js +78 -0
  38. package/packages/web/dist/assets/main-828yzsr7.js +511 -0
  39. package/packages/web/dist/assets/main-828yzsr7.js.map +120 -0
  40. package/packages/web/dist/index.html +1 -1
  41. package/packages/web/dist/sw.js +1 -1
  42. package/packages/web/src/bl/actions.js +226 -104
  43. package/packages/web/src/bl/activity.js +32 -82
  44. package/packages/web/src/bl/index.js +23 -11
  45. package/packages/web/src/bl/launcher.js +2 -9
  46. package/packages/web/src/bl/links.js +31 -18
  47. package/packages/web/src/bl/offline.js +24 -10
  48. package/packages/web/src/bl/pluginInstall.js +29 -26
  49. package/packages/web/src/bl/queries.js +76 -68
  50. package/packages/web/src/bl/services.js +22 -14
  51. package/packages/web/src/bl/social.js +39 -25
  52. package/packages/web/src/bl/state.js +22 -4
  53. package/packages/web/src/bl/viewState.js +9 -0
  54. package/packages/web/src/bl/watchQuery.js +1 -8
  55. package/packages/web/src/dispatch.js +26 -0
  56. package/packages/web/src/platform/api.js +32 -0
  57. package/packages/web/src/platform/commands.js +14 -15
  58. package/packages/web/src/platform/context.js +3 -58
  59. package/packages/web/src/platform/contributions.js +1 -35
  60. package/packages/web/src/platform/fileChunks.js +281 -0
  61. package/packages/web/src/platform/index.js +8 -9
  62. package/packages/web/src/platform/mediaUrls.js +10 -0
  63. package/packages/web/src/platform/navigation.js +35 -21
  64. package/packages/web/src/platform/pickers.js +39 -19
  65. package/packages/web/src/platform/pluginHost.js +4 -1
  66. package/packages/web/src/platform/pluginRpc.js +47 -2
  67. package/packages/web/src/platform/spatialNav.js +1 -1
  68. package/packages/web/src/platform/viewport.js +14 -6
  69. package/packages/web/src/platform/voiceSearch.js +17 -9
  70. package/packages/web/src/platform/whenclause.js +9 -19
  71. package/packages/web/src/runtime.js +2 -37
  72. package/packages/web/src/ui/activate.js +18 -2
  73. package/packages/web/src/ui/components/activityPanel.js +1 -1
  74. package/packages/web/src/ui/components/adminView.js +4 -7
  75. package/packages/web/src/ui/components/editorArea.js +10 -1
  76. package/packages/web/src/ui/components/launcher.js +29 -13
  77. package/packages/web/src/ui/components/openers/index.js +17 -22
  78. package/packages/web/src/ui/components/openers/markdown.js +2 -2
  79. package/packages/web/src/ui/components/overlays.js +31 -5
  80. package/packages/web/src/ui/components/pluginReview.js +7 -4
  81. package/packages/web/src/ui/components/pluginsView.js +1 -1
  82. package/packages/web/src/ui/components/settingsView.js +30 -27
  83. package/packages/web/src/ui/components/statusBar.js +8 -6
  84. package/packages/web/src/ui/components/views/grid.js +2 -2
  85. package/packages/web/src/ui/components/views/parts.js +1 -1
  86. package/packages/web/src/ui/compositions/workbench.js +20 -6
  87. package/packages/web/src/ui/sanitize.js +0 -5
  88. package/packages/web/src/workbench.js +37 -19
  89. package/packages/web/dist/assets/main-c9dnnnc6.js +0 -356
  90. package/packages/web/dist/assets/main-c9dnnnc6.js.map +0 -118
@@ -9,6 +9,15 @@
9
9
  // Both request surfaces need it. The HTTP router obviously; MCP just as much, because
10
10
  // an agent holding Alice's token is Alice and there must be no MCP-shaped way around
11
11
  // the ACL. Written once so the two cannot drift.
12
+ //
13
+ // The same goes for WHO IS ASKING and what that subject may reach. Those helpers lived in
14
+ // routes.js, and mcp/tools.js grew its own copies — which drifted, in the direction that
15
+ // surface makes worst: MCP filtered a named collection out of the readable list, so an
16
+ // agent asking about a collection it may not see was told "No files matched… Try different
17
+ // words" and burned turns rephrasing a permissions error. mcp/index.js claims "It is not a
18
+ // second access-control system to keep in sync with the first"; it was one.
19
+
20
+ import { TroveError } from '@3sln/trove/core';
12
21
 
13
22
  /**
14
23
  * @param {object|null} container the engine container, or null where there is none
@@ -41,3 +50,72 @@ export function leaseScope(container, principal, grant = null) {
41
50
  },
42
51
  };
43
52
  }
53
+
54
+ /**
55
+ * The collections this caller may read, optionally narrowed to one they asked for.
56
+ *
57
+ * Every drive-wide query needs this, and it has to be applied INSIDE the query rather
58
+ * than by filtering results: a LIMIT spent on rows the caller can't see would report
59
+ * "no matches" while matches they can see sit just past the cut.
60
+ *
61
+ * Always a list. It used to answer `undefined` for "don't scope" on a drive with ACLs
62
+ * switched off, and there is no such drive: `collections: false` is refused by
63
+ * `configFromEnv` and again by the provider.
64
+ */
65
+ export async function readableCollectionIds(ctx, narrowTo) {
66
+ // A NAMED collection is asserted, not filtered. Filtering an unreadable id out of the
67
+ // list answers "no results" for a collection the caller may not see — indistinguishable
68
+ // from one that is simply empty, so a permissions problem reads as an indexing problem.
69
+ // `access.collection` throws the 403 that says what actually happened.
70
+ if (narrowTo) {
71
+ await ctx.access.collection(narrowTo, 'read');
72
+ return [narrowTo];
73
+ }
74
+ return (await listFor(ctx)).map((c) => c.id);
75
+ }
76
+
77
+ // --- who is asking ------------------------------------------------------------
78
+ //
79
+ // On a key request `ctx.principal` is NULL and the authority lives on `ctx.grant`, so
80
+ // handing the principal to CollectionService asks about the anonymous caller instead of
81
+ // about the key. That failed in both directions: on a locked drive a correctly-scoped
82
+ // key got `list(null) === []` and 403s from search, tags, backlinks, tasks and issues,
83
+ // while on a `defaultOpen` drive the `anyone` grant let a key scoped to one collection
84
+ // read and write every one of them through those same routes. engine/providers/access.js
85
+ // was the only place that had it right.
86
+ //
87
+ // One helper per question, so "does this surface understand API keys" has one answer
88
+ // rather than one per call site. Never a union of the two: a request bearing a key is
89
+ // the key's request, and falling back to whatever session is attached is how a weak
90
+ // credential borrows a strong one.
91
+
92
+ export const listFor = (ctx) =>
93
+ (ctx.grant ? ctx.collections.listForGrant(ctx.grant) : ctx.collections.list(ctx.principal));
94
+
95
+ export const wholeDriveFor = (ctx) =>
96
+ (ctx.grant ? ctx.collections.grantHasWholeDrive(ctx.grant) : ctx.collections.hasWholeDrive(ctx.principal));
97
+
98
+ /** Returns the collection record, so a caller that needs it does not assert twice. */
99
+ export async function assertCap(ctx, collectionId, capability) {
100
+ return ctx.grant
101
+ ? ctx.collections.assertForGrant(ctx.grant, collectionId, capability)
102
+ : ctx.collections.assert(ctx.principal, collectionId, capability);
103
+ }
104
+
105
+ /** The `describe` that matches whoever asked, so the reported capabilities are theirs. */
106
+ export const describeFor = (ctx, c) =>
107
+ (ctx.grant ? ctx.collections.describeForGrant(c, ctx.grant) : ctx.collections.describe(c, ctx.principal));
108
+
109
+ /**
110
+ * Refuse a request that arrived on an API key.
111
+ *
112
+ * For the collection-ADMINISTRATION verbs, whose authority CollectionService reads from
113
+ * the principal alone. A key request has no principal, so those methods judge it as the
114
+ * anonymous caller — allowing everything on a `defaultOpen` drive and nothing on a locked
115
+ * one. Rather than teach create/update/remove/setGrant about grants, keys stay out: a key
116
+ * that can rewrite a collection's ACL can grant itself whatever it lacks, which is the
117
+ * self-escalation shape `requireHumanAdmin` refuses for the same reason.
118
+ */
119
+ export function refuseGrant(ctx, action) {
120
+ if (ctx.grant) throw TroveError.forbidden(`An API key cannot ${action} — sign in instead`);
121
+ }