@hexis-ai/engram-server 0.11.3 → 0.12.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/dist/adapters/postgres-org-store.d.ts +37 -0
- package/dist/adapters/postgres-org-store.js +102 -0
- package/dist/admin.d.ts +26 -4
- package/dist/admin.js +137 -7
- package/dist/auth-resolver.d.ts +32 -0
- package/dist/auth-resolver.js +53 -0
- package/dist/auth.d.ts +196 -0
- package/dist/auth.js +164 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/main.js +74 -1
- package/dist/migrations/0006-auth.d.ts +2 -0
- package/dist/migrations/0006-auth.js +84 -0
- package/dist/migrations/0007-orgs.d.ts +2 -0
- package/dist/migrations/0007-orgs.js +59 -0
- package/dist/migrations/index.js +4 -0
- package/dist/org-store.d.ts +66 -0
- package/dist/org-store.js +12 -0
- package/dist/server.d.ts +26 -0
- package/dist/server.js +68 -7
- package/package.json +5 -2
package/dist/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
+
import { cors } from "hono/cors";
|
|
2
3
|
import { log, newRequestId } from "./logger";
|
|
3
4
|
import { createAdminRouter } from "./admin";
|
|
4
5
|
import { aliasesRoutes } from "./routes/aliases";
|
|
@@ -39,6 +40,28 @@ export function createServer(opts) {
|
|
|
39
40
|
});
|
|
40
41
|
}
|
|
41
42
|
});
|
|
43
|
+
// CORS — required so engram-web (different origin) can carry the
|
|
44
|
+
// auth cookie. Applies to /auth/* and /v1/* only; admin uses a
|
|
45
|
+
// bearer token from server-side callers and doesn't need CORS.
|
|
46
|
+
if (opts.corsOrigins && opts.corsOrigins.length > 0) {
|
|
47
|
+
const origins = opts.corsOrigins;
|
|
48
|
+
const corsMw = cors({
|
|
49
|
+
origin: (o) => (origins.includes(o) ? o : null),
|
|
50
|
+
credentials: true,
|
|
51
|
+
allowMethods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
|
|
52
|
+
allowHeaders: [
|
|
53
|
+
"content-type",
|
|
54
|
+
"x-api-key",
|
|
55
|
+
"x-workspace-id",
|
|
56
|
+
"x-request-id",
|
|
57
|
+
"authorization",
|
|
58
|
+
],
|
|
59
|
+
exposeHeaders: ["x-request-id"],
|
|
60
|
+
maxAge: 600,
|
|
61
|
+
});
|
|
62
|
+
app.use("/auth/*", corsMw);
|
|
63
|
+
app.use("/v1/*", corsMw);
|
|
64
|
+
}
|
|
42
65
|
app.onError((err, c) => {
|
|
43
66
|
log.error("unhandled", {
|
|
44
67
|
request_id: c.var.request_id,
|
|
@@ -71,22 +94,60 @@ export function createServer(opts) {
|
|
|
71
94
|
if (opts.admin) {
|
|
72
95
|
app.route("/admin/v1", createAdminRouter(opts.admin));
|
|
73
96
|
}
|
|
74
|
-
//
|
|
97
|
+
// better-auth catchall. Mounted before `/v1` so /auth/* never falls
|
|
98
|
+
// through to the workspace gate.
|
|
99
|
+
if (opts.authHandler) {
|
|
100
|
+
const handler = opts.authHandler;
|
|
101
|
+
app.all("/auth/*", (c) => handler.handler(c.req.raw));
|
|
102
|
+
}
|
|
103
|
+
// Workspace auth gate — every `/v1/*` route runs behind this. Tries
|
|
104
|
+
// api-key first; falls back to cookie session when configured. The
|
|
105
|
+
// Bearer header is reserved for api-keys here; engram-web uses the
|
|
106
|
+
// session cookie, not a Bearer.
|
|
75
107
|
app.use("/v1/*", async (c, next) => {
|
|
76
108
|
const apiKey = c.req.header("x-api-key") ??
|
|
77
109
|
c.req.header("authorization")?.match(/^Bearer\s+(.+)$/i)?.[1];
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
110
|
+
let ctx = apiKey ? await opts.auth(apiKey) : null;
|
|
111
|
+
if (!ctx && !apiKey && opts.cookieAuth) {
|
|
112
|
+
ctx = await opts.cookieAuth(c.req.raw);
|
|
113
|
+
}
|
|
81
114
|
if (!ctx)
|
|
82
115
|
return c.json({ error: "unauthorized" }, 401);
|
|
83
116
|
c.set("ctx", ctx);
|
|
84
117
|
await next();
|
|
85
118
|
});
|
|
86
|
-
// Identity probe — echoes the workspace the caller's
|
|
87
|
-
//
|
|
88
|
-
// which tenant they're viewing.
|
|
119
|
+
// Identity probe — echoes the workspace the caller's auth
|
|
120
|
+
// resolves to. Cheap, used as a health/whoami by clients.
|
|
89
121
|
app.get("/v1/me", (c) => c.json({ workspaceId: c.var.ctx.workspaceId }));
|
|
122
|
+
// Cookie-auth helpers for engram-web: list every workspace / org
|
|
123
|
+
// the signed-in user can reach. api-key callers don't need these
|
|
124
|
+
// (they already know which workspace they're scoped to).
|
|
125
|
+
if (opts.authHandler && opts.orgStore) {
|
|
126
|
+
const auth = opts.authHandler;
|
|
127
|
+
const orgStore = opts.orgStore;
|
|
128
|
+
const requireUser = async (req) => {
|
|
129
|
+
const s = await auth.api.getSession({ headers: req.headers }).catch(() => null);
|
|
130
|
+
return s?.user ?? null;
|
|
131
|
+
};
|
|
132
|
+
app.get("/v1/me/workspaces", async (c) => {
|
|
133
|
+
const user = await requireUser(c.req.raw);
|
|
134
|
+
if (!user)
|
|
135
|
+
return c.json({ error: "unauthorized" }, 401);
|
|
136
|
+
const workspaces = await orgStore.listWorkspacesForUser(user.id);
|
|
137
|
+
return c.json({ workspaces });
|
|
138
|
+
});
|
|
139
|
+
app.get("/v1/me/orgs", async (c) => {
|
|
140
|
+
const user = await requireUser(c.req.raw);
|
|
141
|
+
if (!user)
|
|
142
|
+
return c.json({ error: "unauthorized" }, 401);
|
|
143
|
+
const memberships = await orgStore.listOrgsForUser(user.id);
|
|
144
|
+
const orgs = await Promise.all(memberships.map(async (m) => ({
|
|
145
|
+
...(await orgStore.getOrg(m.orgId)),
|
|
146
|
+
role: m.role,
|
|
147
|
+
})));
|
|
148
|
+
return c.json({ orgs: orgs.filter((o) => o.id) });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
90
151
|
app.route("/v1", sessionsRoutes(cfg));
|
|
91
152
|
app.route("/v1", personsRoutes(cfg));
|
|
92
153
|
app.route("/v1", identitiesRoutes(cfg));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexis-ai/engram-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Engram server: ingest agent session events, persist via a pluggable adapter, expose search.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"engram",
|
|
@@ -50,8 +50,10 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@hexis-ai/engram-core": "^0.2.0",
|
|
53
|
-
"@hexis-ai/engram-sdk": "^0.
|
|
53
|
+
"@hexis-ai/engram-sdk": "^0.13.0",
|
|
54
|
+
"better-auth": "^1.6.11",
|
|
54
55
|
"hono": "^4.6.0",
|
|
56
|
+
"pg": "^8.13.0",
|
|
55
57
|
"zod": "^4.0.0"
|
|
56
58
|
},
|
|
57
59
|
"peerDependencies": {
|
|
@@ -63,6 +65,7 @@
|
|
|
63
65
|
}
|
|
64
66
|
},
|
|
65
67
|
"devDependencies": {
|
|
68
|
+
"@types/pg": "^8.11.10",
|
|
66
69
|
"postgres": "^3.4.0"
|
|
67
70
|
},
|
|
68
71
|
"publishConfig": {
|