@hasna/contacts 0.6.35 → 0.7.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.
Files changed (55) hide show
  1. package/README.md +53 -60
  2. package/dist/cli/commands/advanced.d.ts.map +1 -1
  3. package/dist/cli/commands/core.d.ts +1 -1
  4. package/dist/cli/commands/core.d.ts.map +1 -1
  5. package/dist/cli/commands/crm.d.ts.map +1 -1
  6. package/dist/cli/index.js +9137 -38536
  7. package/dist/cli/legacy.d.ts +18 -0
  8. package/dist/cli/legacy.d.ts.map +1 -0
  9. package/dist/cli/status-domain.preload.d.ts +2 -0
  10. package/dist/cli/status-domain.preload.d.ts.map +1 -0
  11. package/dist/cli/storage.d.ts.map +1 -1
  12. package/dist/cloud/client-config.d.ts +6 -0
  13. package/dist/cloud/client-config.d.ts.map +1 -0
  14. package/dist/cloud/http-storage.d.ts +40 -69
  15. package/dist/cloud/http-storage.d.ts.map +1 -1
  16. package/dist/db/database.d.ts +1 -1
  17. package/dist/db/database.d.ts.map +1 -1
  18. package/dist/db/paths.d.ts +18 -0
  19. package/dist/db/paths.d.ts.map +1 -1
  20. package/dist/generated/storage-kit/index.d.ts +0 -1
  21. package/dist/generated/storage-kit/index.d.ts.map +1 -1
  22. package/dist/generated/storage-kit/pool.d.ts +13 -3
  23. package/dist/generated/storage-kit/pool.d.ts.map +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +373 -5573
  26. package/dist/lib/images.d.ts.map +1 -1
  27. package/dist/lib/vault.d.ts +5 -1
  28. package/dist/lib/vault.d.ts.map +1 -1
  29. package/dist/mcp/handlers/advanced.d.ts.map +1 -1
  30. package/dist/mcp/handlers/core.d.ts +1 -1
  31. package/dist/mcp/index.js +816 -5805
  32. package/dist/mcp/storage-tools.d.ts.map +1 -1
  33. package/dist/mcp/tools.d.ts +3 -3
  34. package/dist/sdk/index.d.ts +15 -13
  35. package/dist/sdk/index.d.ts.map +1 -1
  36. package/dist/sdk/index.js +44 -1
  37. package/dist/server/cloud.d.ts +6 -7
  38. package/dist/server/cloud.d.ts.map +1 -1
  39. package/dist/server/index.d.ts +2 -1
  40. package/dist/server/index.d.ts.map +1 -1
  41. package/dist/server/index.js +3744 -34863
  42. package/dist/server/security.d.ts +1 -1
  43. package/dist/server/security.d.ts.map +1 -1
  44. package/dist/server/serve.d.ts.map +1 -1
  45. package/dist/store/index.d.ts +66 -93
  46. package/dist/store/index.d.ts.map +1 -1
  47. package/dist/types/store-dto.d.ts +273 -0
  48. package/dist/types/store-dto.d.ts.map +1 -0
  49. package/hasna.contract.json +63 -10
  50. package/package.json +22 -11
  51. package/dashboard/dist/assets/index-0l6aQb1t.css +0 -1
  52. package/dashboard/dist/assets/index-opnZdkVD.js +0 -229
  53. package/dashboard/dist/index.html +0 -13
  54. package/dist/generated/storage-kit/mode.d.ts +0 -48
  55. package/dist/generated/storage-kit/mode.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"storage-tools.d.ts","sourceRoot":"","sources":["../../src/mcp/storage-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA0CzE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4CpE"}
1
+ {"version":3,"file":"storage-tools.d.ts","sourceRoot":"","sources":["../../src/mcp/storage-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8BzE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAapE"}
@@ -3136,7 +3136,7 @@ export declare const TOOL_DEFINITIONS: readonly [{
3136
3136
  };
3137
3137
  }, {
3138
3138
  readonly name: "set_contact_photo";
3139
- readonly description: "Set a contact's profile photo. Provide either a local file path or base64-encoded image data (with or without data URI prefix). Stores image in ~/.hasna/contacts/images/ and updates avatar_url. Supported formats: jpg, png, gif, webp, svg, avif.";
3139
+ readonly description: "Set a contact's profile photo. Provide either a local file path or base64-encoded image data (with or without data URI prefix). Stores image in the XDG data root images dir and updates avatar_url. Supported formats: jpg, png, gif, webp, svg, avif.";
3140
3140
  readonly inputSchema: {
3141
3141
  readonly type: "object";
3142
3142
  readonly properties: {
@@ -3180,7 +3180,7 @@ export declare const TOOL_DEFINITIONS: readonly [{
3180
3180
  };
3181
3181
  }, {
3182
3182
  readonly name: "set_company_logo";
3183
- readonly description: "Set a company's logo image. Provide either a local file path or base64-encoded image data. Stores image in ~/.hasna/contacts/images/ and updates logo_url.";
3183
+ readonly description: "Set a company's logo image. Provide either a local file path or base64-encoded image data. Stores image in the XDG data root images dir and updates logo_url.";
3184
3184
  readonly inputSchema: {
3185
3185
  readonly type: "object";
3186
3186
  readonly properties: {
@@ -3298,7 +3298,7 @@ export declare const TOOL_DEFINITIONS: readonly [{
3298
3298
  };
3299
3299
  readonly file_path: {
3300
3300
  readonly type: "string";
3301
- readonly description: "File to attach — stored PLAIN in ~/.hasna/contacts/documents/ for agent access";
3301
+ readonly description: "File to attach — stored PLAIN in the XDG data root documents dir for agent access";
3302
3302
  };
3303
3303
  readonly metadata: {
3304
3304
  readonly type: "object";
@@ -1,16 +1,18 @@
1
+ /** @hasna/contacts SDK — explicit authenticated HTTPS `/v1` client. */
2
+ import { ContactsV1Client as GeneratedContactsV1Client, ApiError, type ContactsV1ClientOptions as GeneratedContactsV1ClientOptions } from "./v1.generated.js";
3
+ export interface ContactsV1ClientOptions extends Omit<GeneratedContactsV1ClientOptions, "baseUrl" | "apiKey"> {
4
+ /** Explicit HTTPS service authority. No default is composed. */
5
+ baseUrl: string;
6
+ /** API key sent to the configured authority. Required and never logged. */
7
+ apiKey: string;
8
+ }
1
9
  /**
2
- * @hasna/contacts SDK typed `/v1` cloud client.
3
- *
4
- * Generated from the serve OpenAPI document (src/server/openapi.ts).
5
- * Regenerate with `bun run scripts/generate-sdk.ts`.
6
- *
7
- * import { ContactsV1Client } from "@hasna/contacts/sdk";
8
- * const client = new ContactsV1Client({
9
- * baseUrl: process.env.CONTACTS_API_URL!, // self_hosted service URL
10
- * apiKey: process.env.CONTACTS_API_KEY!, // contracts-issued key
11
- * });
12
- * const { contacts } = await client.listContacts({ limit: 20 });
10
+ * Validated wrapper around the generated API surface. Redirects are never
11
+ * followed, so credentials cannot cross to another authority.
13
12
  */
14
- export { ContactsV1Client, ApiError as ContactsV1ApiError } from "./v1.generated.js";
15
- export type { ContactsV1ClientOptions, Contact as ContactsV1Contact, Company as ContactsV1Company, Tag as ContactsV1Tag, CreateContactInput as ContactsV1CreateContactInput, UpdateContactInput as ContactsV1UpdateContactInput, CreateCompanyInput as ContactsV1CreateCompanyInput, UpdateCompanyInput as ContactsV1UpdateCompanyInput, CreateTagInput as ContactsV1CreateTagInput, UpdateTagInput as ContactsV1UpdateTagInput, ProjectIdsInput as ContactsV1ProjectIdsInput, ContactProjectMembershipSnapshot as ContactsV1ProjectMembershipSnapshot, ContactProjectMembershipMutationInput as ContactsV1ProjectMembershipMutationInput, ContactProjectMembershipMutationResult as ContactsV1ProjectMembershipMutationResult, ContactProjectMembershipListResult as ContactsV1ProjectMembershipListResult, } from "./v1.generated.js";
13
+ export declare class ContactsV1Client extends GeneratedContactsV1Client {
14
+ constructor(options: ContactsV1ClientOptions);
15
+ }
16
+ export { ApiError as ContactsV1ApiError };
17
+ export type { Contact as ContactsV1Contact, Company as ContactsV1Company, Tag as ContactsV1Tag, CreateContactInput as ContactsV1CreateContactInput, UpdateContactInput as ContactsV1UpdateContactInput, CreateCompanyInput as ContactsV1CreateCompanyInput, UpdateCompanyInput as ContactsV1UpdateCompanyInput, CreateTagInput as ContactsV1CreateTagInput, UpdateTagInput as ContactsV1UpdateTagInput, ProjectIdsInput as ContactsV1ProjectIdsInput, ContactProjectMembershipSnapshot as ContactsV1ProjectMembershipSnapshot, ContactProjectMembershipMutationInput as ContactsV1ProjectMembershipMutationInput, ContactProjectMembershipMutationResult as ContactsV1ProjectMembershipMutationResult, ContactProjectMembershipListResult as ContactsV1ProjectMembershipListResult, } from "./v1.generated.js";
16
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,gBAAgB,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACrF,YAAY,EACV,uBAAuB,EACvB,OAAO,IAAI,iBAAiB,EAC5B,OAAO,IAAI,iBAAiB,EAC5B,GAAG,IAAI,aAAa,EACpB,kBAAkB,IAAI,4BAA4B,EAClD,kBAAkB,IAAI,4BAA4B,EAClD,kBAAkB,IAAI,4BAA4B,EAClD,kBAAkB,IAAI,4BAA4B,EAClD,cAAc,IAAI,wBAAwB,EAC1C,cAAc,IAAI,wBAAwB,EAC1C,eAAe,IAAI,yBAAyB,EAC5C,gCAAgC,IAAI,mCAAmC,EACvE,qCAAqC,IAAI,wCAAwC,EACjF,sCAAsC,IAAI,yCAAyC,EACnF,kCAAkC,IAAI,qCAAqC,GAC5E,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EACL,gBAAgB,IAAI,yBAAyB,EAC7C,QAAQ,EACR,KAAK,uBAAuB,IAAI,gCAAgC,EACjE,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,gCAAgC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpE,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;CAChB;AA8BD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,yBAAyB;gBACjD,OAAO,EAAE,uBAAuB;CAS7C;AAED,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,CAAC;AAC1C,YAAY,EACV,OAAO,IAAI,iBAAiB,EAC5B,OAAO,IAAI,iBAAiB,EAC5B,GAAG,IAAI,aAAa,EACpB,kBAAkB,IAAI,4BAA4B,EAClD,kBAAkB,IAAI,4BAA4B,EAClD,kBAAkB,IAAI,4BAA4B,EAClD,kBAAkB,IAAI,4BAA4B,EAClD,cAAc,IAAI,wBAAwB,EAC1C,cAAc,IAAI,wBAAwB,EAC1C,eAAe,IAAI,yBAAyB,EAC5C,gCAAgC,IAAI,mCAAmC,EACvE,qCAAqC,IAAI,wCAAwC,EACjF,sCAAsC,IAAI,yCAAyC,EACnF,kCAAkC,IAAI,qCAAqC,GAC5E,MAAM,mBAAmB,CAAC"}
package/dist/sdk/index.js CHANGED
@@ -244,7 +244,50 @@ class ContactsV1Client {
244
244
  });
245
245
  }
246
246
  }
247
+
248
+ // src/sdk/index.ts
249
+ function validateBaseUrl(raw) {
250
+ let url;
251
+ try {
252
+ url = new URL(raw);
253
+ } catch {
254
+ throw new Error("ContactsV1Client baseUrl must be an absolute HTTPS URL.");
255
+ }
256
+ if (url.protocol !== "https:")
257
+ throw new Error("ContactsV1Client baseUrl must use HTTPS.");
258
+ if (url.username || url.password)
259
+ throw new Error("ContactsV1Client baseUrl must not contain credentials.");
260
+ if (url.search || url.hash)
261
+ throw new Error("ContactsV1Client baseUrl must not contain a query or fragment.");
262
+ const path = url.pathname.replace(/\/+$/, "");
263
+ if (path && path !== "/v1") {
264
+ throw new Error("ContactsV1Client baseUrl must be an authority root or end in /v1.");
265
+ }
266
+ url.pathname = "";
267
+ return url.toString().replace(/\/+$/, "");
268
+ }
269
+ function validateApiKey(apiKey) {
270
+ const key = apiKey.trim();
271
+ if (!key)
272
+ throw new Error("ContactsV1Client requires an API key.");
273
+ if (/[^\t\x20-\x7e]/.test(key)) {
274
+ throw new Error("ContactsV1Client API key contains bytes that are invalid in an HTTP header.");
275
+ }
276
+ return key;
277
+ }
278
+
279
+ class ContactsV1Client2 extends ContactsV1Client {
280
+ constructor(options) {
281
+ const fetchImpl = options.fetch ?? globalThis.fetch;
282
+ super({
283
+ ...options,
284
+ baseUrl: validateBaseUrl(options.baseUrl),
285
+ apiKey: validateApiKey(options.apiKey),
286
+ fetch: (input, init) => fetchImpl(input, { ...init, redirect: "manual" })
287
+ });
288
+ }
289
+ }
247
290
  export {
248
- ContactsV1Client,
291
+ ContactsV1Client2 as ContactsV1Client,
249
292
  ApiError as ContactsV1ApiError
250
293
  };
@@ -1,23 +1,22 @@
1
1
  /**
2
- * Cloud (A1 pure-remote) service wiring for `contacts-serve`.
2
+ * PostgreSQL service wiring for `contacts-serve`.
3
3
  *
4
4
  * This module powers the versioned `/v1` API and its API-key auth. Per Amendment
5
5
  * A1 the serve process reads and writes the shared RDS Postgres DIRECTLY through
6
6
  * the vendored @hasna/contracts storage kit — there is NO local sync/cache in
7
7
  * the service. Everything is lazy: nothing touches Postgres or crypto until the
8
- * first `/v1` / `/ready` request, so the local-first CLI/dashboard SQLite paths
9
- * keep ZERO cloud dependencies.
8
+ * first `/v1` / `/ready` request. Public clients never import this server-only
9
+ * PostgreSQL boundary.
10
10
  */
11
11
  import { ApiKeyStore, type ApiKeyVerifier } from "@hasna/contracts/auth";
12
- import type { PoolQueryClient } from "../generated/storage-kit/query.js";
12
+ import { type PoolQueryClient } from "../generated/storage-kit/query.js";
13
13
  export declare const CONTACTS_APP_SLUG = "contacts";
14
+ export declare function validatePostgresDatabaseUrl(value: string): string;
14
15
  /** Resolve the remote DATABASE_URL from the supported env vars (priority order). */
15
16
  export declare function resolveCloudDatabaseUrl(env?: NodeJS.ProcessEnv): string | undefined;
16
17
  /** Resolve the HMAC signing secret used to verify API keys. */
17
18
  export declare function resolveSigningSecret(env?: NodeJS.ProcessEnv): string | undefined;
18
- /** True when this process is configured to serve the cloud `/v1` API.
19
- * Explicit remote mode remains cloud even when its DSN is missing so readiness
20
- * fails closed instead of presenting the process as a healthy local server. */
19
+ /** True when this server process has its PostgreSQL backend configured. */
21
20
  export declare function isCloudModeEnabled(env?: NodeJS.ProcessEnv): boolean;
22
21
  /** The vendored-kit Postgres pool client backing every `/v1` handler. */
23
22
  export declare function getCloudClient(): PoolQueryClient;
@@ -1 +1 @@
1
- {"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../../src/server/cloud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAgB,WAAW,EAAE,KAAK,cAAc,EAAwB,MAAM,uBAAuB,CAAC;AAE7G,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAIzE,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAE5C,oFAAoF;AACpF,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAOhG;AAED,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAO7F;AAED;;+EAE+E;AAC/E,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAGhF;AAQD,yEAAyE;AACzE,wBAAgB,cAAc,IAAI,eAAe,CA2BhD;AAYD,wBAAgB,cAAc,IAAI,WAAW,CAI5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,CAejD;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAUvD;AAED;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAYjE;AAED,iEAAiE;AACjE,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAGlD;AAED,4BAA4B;AAC5B,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAOhD"}
1
+ {"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../../src/server/cloud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAgB,WAAW,EAAE,KAAK,cAAc,EAAwB,MAAM,uBAAuB,CAAC;AAE7G,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAI5F,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAU5C,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASjE;AAED,oFAAoF;AACpF,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAGhG;AAED,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAE7F;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAEhF;AAQD,yEAAyE;AACzE,wBAAgB,cAAc,IAAI,eAAe,CAoBhD;AAYD,wBAAgB,cAAc,IAAI,WAAW,CAI5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,CAejD;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAUvD;AAED;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAYjE;AAED,iEAAiE;AACjE,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAGlD;AAED,4BAA4B;AAC5B,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAOhD"}
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env bun
2
- export {};
2
+ /** Canonical contacts-serve entrypoint: authenticated `/v1` over PostgreSQL. */
3
+ import "./cloud-index.js";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA,gFAAgF;AAChF,OAAO,kBAAkB,CAAC"}