drafted 1.25.9 → 1.25.10
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/mcp/server.mjs +18 -2
- package/package.json +1 -1
package/mcp/server.mjs
CHANGED
|
@@ -1634,7 +1634,14 @@ async function resolveProjectRef(ref, orgHint = null) {
|
|
|
1634
1634
|
if (!ref) return null;
|
|
1635
1635
|
const cacheKey = orgHint ? `${orgHint}|${ref}` : ref;
|
|
1636
1636
|
const hit = projectRefCache.get(cacheKey) || (!orgHint && projectRefCache.get(ref));
|
|
1637
|
-
|
|
1637
|
+
// Keep the BARE-ref key in step with a scoped hit. The fs route resolves the
|
|
1638
|
+
// path's project twice: once with the path's org as the hint (the guard, and
|
|
1639
|
+
// the state it records), once without one — and that second pass is what scopes
|
|
1640
|
+
// the call. The unhinted pass reads `ref`, which every resolve in any org
|
|
1641
|
+
// rewrites, so without this the two passes could name different orgs' projects:
|
|
1642
|
+
// with `architecture` in two orgs, read home → read other → read home answered
|
|
1643
|
+
// `project "architecture" is not in the addressed org` for a correct path.
|
|
1644
|
+
if (hit) { projectRefCache.set(ref, hit); return hit; }
|
|
1638
1645
|
// Scope the lookup to the org the path named. Without a hint the session's
|
|
1639
1646
|
// org applies — which is right for `fs ls /projects` but WRONG for a path
|
|
1640
1647
|
// that addressed another org, and that mismatch is what made a project
|
|
@@ -1647,6 +1654,7 @@ async function resolveProjectRef(ref, orgHint = null) {
|
|
|
1647
1654
|
rows.find(x => String(x.slug || '').toLowerCase() === want) ||
|
|
1648
1655
|
rows.find(x => String(x.name || '').toLowerCase() === want);
|
|
1649
1656
|
let p = pick(list);
|
|
1657
|
+
const fromHintOrg = !!p;
|
|
1650
1658
|
// A miss is worth one unscoped look before "not found": the hint may be stale
|
|
1651
1659
|
// (a project that moved org), and an id passed as projectId= carries no org at
|
|
1652
1660
|
// all — only a UUID can name a project in an org the session is not inside.
|
|
@@ -1659,7 +1667,15 @@ async function resolveProjectRef(ref, orgHint = null) {
|
|
|
1659
1667
|
// `folder` rides along so a caller can rebuild the project's printed address
|
|
1660
1668
|
// (/o/<org>/projects/<folder>/<slug>) without a second lookup.
|
|
1661
1669
|
const meta = { id: p.id, slug: p.slug || null, name: p.name || null, orgId: p.orgId || null, orgSlug: p.orgSlug || null, folder: p.folder || '' };
|
|
1662
|
-
|
|
1670
|
+
// `<org>|<ref>` means "this ref IN THAT ORG", so only an answer that came out of
|
|
1671
|
+
// that org's own listing may be stored under it. A cross-org fallback answer
|
|
1672
|
+
// stored there is re-served to every later path naming that org, and the org
|
|
1673
|
+
// guard then rejects a project the path never asked for: fs read/write on
|
|
1674
|
+
// /o/<org-slug>/projects/<name>/... answered "project <name> is not in org
|
|
1675
|
+
// <slug>" after one miss (a mkdir of a name another org owned) cached a foreign
|
|
1676
|
+
// project under the slug, while the same path spelled with the org UUID — a
|
|
1677
|
+
// different key — still resolved. Measured on prod 1.25.9.
|
|
1678
|
+
if (fromHintOrg || !orgHint) projectRefCache.set(cacheKey, meta);
|
|
1663
1679
|
projectRefCache.set(ref, meta);
|
|
1664
1680
|
projectRefCache.set(p.id, meta);
|
|
1665
1681
|
return meta;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.10",
|
|
4
4
|
"description": "Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|