@hasna/contacts 0.7.0 → 0.8.1
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/README.md +83 -13
- package/dist/cli/commands/core.d.ts.map +1 -1
- package/dist/cli/index.js +82 -33
- package/dist/cloud/http-storage.d.ts +20 -12
- package/dist/cloud/http-storage.d.ts.map +1 -1
- package/dist/cloud/resolver-inputs.d.ts +51 -0
- package/dist/cloud/resolver-inputs.d.ts.map +1 -0
- package/dist/db/paths.d.ts +4 -4
- package/dist/db/paths.d.ts.map +1 -1
- package/dist/generated/storage-kit/backend.d.ts +19 -0
- package/dist/generated/storage-kit/backend.d.ts.map +1 -0
- package/dist/generated/storage-kit/index.d.ts +2 -1
- package/dist/generated/storage-kit/index.d.ts.map +1 -1
- package/dist/generated/storage-kit/migrations.d.ts +21 -0
- package/dist/generated/storage-kit/migrations.d.ts.map +1 -1
- package/dist/generated/storage-kit/own.d.ts +11 -0
- package/dist/generated/storage-kit/own.d.ts.map +1 -0
- package/dist/generated/storage-kit/pool.d.ts +5 -17
- package/dist/generated/storage-kit/pool.d.ts.map +1 -1
- package/dist/generated/storage-kit/query.d.ts +1 -1
- package/dist/generated/storage-kit/query.d.ts.map +1 -1
- package/dist/generated/storage-kit/tls.d.ts +30 -3
- package/dist/generated/storage-kit/tls.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +105 -24
- package/dist/mcp/index.d.ts +9 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +112 -18
- package/dist/mcp/startup-gate.d.ts +48 -0
- package/dist/mcp/startup-gate.d.ts.map +1 -0
- package/dist/sdk/index.d.ts +70 -3
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +990 -7
- package/dist/server/index.js +201 -43
- package/hasna.contract.json +20 -6
- package/package.json +3 -3
- package/dist/lib/config.d.ts +0 -7
- package/dist/lib/config.d.ts.map +0 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type CredentialChainOptions, type ResolvedCredential } from "@hasna/contracts/client";
|
|
2
|
+
import { type Env } from "../cloud/resolver-inputs.js";
|
|
3
|
+
/**
|
|
4
|
+
* The fail-closed startup gate for `contacts-mcp` (hasna/apps#1720 validation,
|
|
5
|
+
* round 2).
|
|
6
|
+
*
|
|
7
|
+
* A hosted-only client with no credential must fail LOUD before it serves:
|
|
8
|
+
* non-zero exit before the stdio transport is connected or the HTTP port is
|
|
9
|
+
* bound, so an agent that registered `contacts-mcp` on a station without the
|
|
10
|
+
* fleet credential sees the refusal at startup instead of an `initialize`
|
|
11
|
+
* answered by a server whose every tool call would fail. Previously main()
|
|
12
|
+
* built the server and connected the transport without ever resolving the
|
|
13
|
+
* credential: the negative control (empty HASNA_HOME, absent Keychain
|
|
14
|
+
* account, no env key) printed "running on stdio", answered `initialize`,
|
|
15
|
+
* and exited 0.
|
|
16
|
+
*
|
|
17
|
+
* The gate is ONE pass down the same @hasna/contracts chain the tools resolve
|
|
18
|
+
* through per call (`resolveContactsClientTransport`): the live process
|
|
19
|
+
* environment keeps its ambient Keychain/disk tiers, a caller-built env is the
|
|
20
|
+
* hermetic seam. A DELIBERATE tier that cannot produce a key is a refusal,
|
|
21
|
+
* never resolved around: `HASNA_PROFILE` naming a missing profile file, an
|
|
22
|
+
* unsafe credentials file, a Keychain item that exists but cannot be read, and
|
|
23
|
+
* the secrets-vault pointer `HASNA_CONTACTS_API_KEY_REF`. The chain validates
|
|
24
|
+
* only the pointer's SHAPE, so the gate dereferences it once through the vault
|
|
25
|
+
* exactly as the transport does at request time; a pointer that cannot be
|
|
26
|
+
* completed (SDK absent, vault unconfigured or unreachable, item missing or
|
|
27
|
+
* empty) refuses the start instead of answering `initialize` with a server
|
|
28
|
+
* whose every call would fail.
|
|
29
|
+
*
|
|
30
|
+
* Nothing here opens, reads or creates a local store, and the message names
|
|
31
|
+
* WHERE the credential should live (an item reference, a file path, an env key
|
|
32
|
+
* name) — never a value. A dereferenced key is dropped on the spot: every tool
|
|
33
|
+
* still re-resolves per call.
|
|
34
|
+
*/
|
|
35
|
+
export type McpStartupGate = {
|
|
36
|
+
ok: true;
|
|
37
|
+
apiUrlSource: string | null;
|
|
38
|
+
apiKeySource: string | null;
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
message: string;
|
|
42
|
+
};
|
|
43
|
+
/** The vault dereference, injectable so the pointer path is testable without a vault. */
|
|
44
|
+
export interface McpStartupGateOptions {
|
|
45
|
+
completePointer?: (name: string, pointer: ResolvedCredential, env: Env) => Promise<ResolvedCredential>;
|
|
46
|
+
}
|
|
47
|
+
export declare function resolveMcpStartupGate(env?: Env, credentials?: CredentialChainOptions, options?: McpStartupGateOptions): Promise<McpStartupGate>;
|
|
48
|
+
//# sourceMappingURL=startup-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup-gate.d.ts","sourceRoot":"","sources":["../../src/mcp/startup-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAA+B,KAAK,GAAG,EAAE,MAAM,6BAA6B,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACtE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACpC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACxG;AAOD,wBAAsB,qBAAqB,CACzC,GAAG,GAAE,GAAiB,EACtB,WAAW,GAAE,sBAA2B,EACxC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,cAAc,CAAC,CAmCzB"}
|
package/dist/sdk/index.d.ts
CHANGED
|
@@ -1,10 +1,37 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* @hasna/contacts SDK — the hosted `/v1` client surface.
|
|
3
|
+
*
|
|
4
|
+
* Two constructors, one rule (hasna/apps#1720, #1794):
|
|
5
|
+
*
|
|
6
|
+
* - `new ContactsV1Client({ baseUrl, apiKey })` is the EXPLICIT pin: a
|
|
7
|
+
* caller-supplied authority is a deliberate selection, it always requires a
|
|
8
|
+
* caller-supplied key, and the ambient fleet credential is never attached to
|
|
9
|
+
* it.
|
|
10
|
+
* - `createContactsClient()` goes through the ONE fleet resolver in
|
|
11
|
+
* `@hasna/contracts/client`, exactly like the CLI and the MCP server: the
|
|
12
|
+
* credential comes from an explicit argument, the deliberate env pointers
|
|
13
|
+
* (`HASNA_CONTACTS_API_KEY_OVERRIDE`, `HASNA_PROFILE`,
|
|
14
|
+
* `HASNA_CONTACTS_API_KEY_REF`), the macOS Keychain item
|
|
15
|
+
* `hasna.credentials.contacts.api-key`, `~/.hasna/contacts/config/credentials`
|
|
16
|
+
* (owner-only 0400/0600), then `HASNA_CONTACTS_API_KEY`; the authority follows
|
|
17
|
+
* `HASNA_CONTACTS_API_URL`, the Keychain `api-url` item, the credentials
|
|
18
|
+
* file, and defaults to the fleet gateway `https://api.hasna.com/contacts`
|
|
19
|
+
* once a credential resolves. The KEY is re-resolved on every request (a
|
|
20
|
+
* rotation heals a long-lived agent); the AUTHORITY is pinned for the life
|
|
21
|
+
* of the client, so a credential written for one service is never sent to
|
|
22
|
+
* another. Nothing resolving THROWS — there is no local fallback and no
|
|
23
|
+
* unauthenticated client.
|
|
24
|
+
*/
|
|
25
|
+
import { type KeychainTierOptions } from "@hasna/contracts/client";
|
|
26
|
+
import { ContactsClientConfigurationError } from "../cloud/http-storage.js";
|
|
27
|
+
import { type Env } from "../cloud/resolver-inputs.js";
|
|
2
28
|
import { ContactsV1Client as GeneratedContactsV1Client, ApiError, type ContactsV1ClientOptions as GeneratedContactsV1ClientOptions } from "./v1.generated.js";
|
|
3
29
|
export interface ContactsV1ClientOptions extends Omit<GeneratedContactsV1ClientOptions, "baseUrl" | "apiKey"> {
|
|
4
30
|
/** Explicit HTTPS service authority. No default is composed. */
|
|
5
31
|
baseUrl: string;
|
|
6
|
-
/** API key sent to the configured authority. Required and never logged.
|
|
7
|
-
|
|
32
|
+
/** API key sent to the configured authority. Required and never logged.
|
|
33
|
+
* An explicit baseUrl never falls back to an ambient fleet key (#1794). */
|
|
34
|
+
apiKey?: string;
|
|
8
35
|
}
|
|
9
36
|
/**
|
|
10
37
|
* Validated wrapper around the generated API surface. Redirects are never
|
|
@@ -13,6 +40,46 @@ export interface ContactsV1ClientOptions extends Omit<GeneratedContactsV1ClientO
|
|
|
13
40
|
export declare class ContactsV1Client extends GeneratedContactsV1Client {
|
|
14
41
|
constructor(options: ContactsV1ClientOptions);
|
|
15
42
|
}
|
|
43
|
+
/** The app slug the shared client seam resolves credentials and authority for. */
|
|
44
|
+
export declare const CONTACTS_APP_NAME: "contacts";
|
|
45
|
+
/** Options for {@link createContactsClient}. */
|
|
46
|
+
export interface CreateContactsClientOptions extends Omit<GeneratedContactsV1ClientOptions, "baseUrl" | "apiKey"> {
|
|
47
|
+
/**
|
|
48
|
+
* Explicit HTTPS authority — a deliberate pin. Requires `apiKey`; the ambient
|
|
49
|
+
* chain is never consulted on its behalf (#1794).
|
|
50
|
+
*/
|
|
51
|
+
baseUrl?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Explicit API key (tier 1). With `baseUrl` it is the whole configuration;
|
|
54
|
+
* alone, the authority still resolves through the chain.
|
|
55
|
+
*/
|
|
56
|
+
apiKey?: string;
|
|
57
|
+
/** The environment to resolve through instead of `process.env` — the hermetic seam. */
|
|
58
|
+
env?: Env;
|
|
59
|
+
/** Tier-1 identity selection (`--profile`), passed through to the chain. */
|
|
60
|
+
profile?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Tier-3 controls: a fake `security` runner in tests, an opt-out on a CI
|
|
63
|
+
* Mac. Production callers pass nothing — the tier is ambient for
|
|
64
|
+
* `process.env` and off for a caller-built env.
|
|
65
|
+
*/
|
|
66
|
+
keychain?: KeychainTierOptions;
|
|
67
|
+
}
|
|
68
|
+
/** The SDK's refusal for an explicit authority without an explicit key (#1794). */
|
|
69
|
+
export declare function contactsSdkAuthorityPinMessage(): string;
|
|
70
|
+
/**
|
|
71
|
+
* Build a ContactsV1Client through the fleet resolver.
|
|
72
|
+
*
|
|
73
|
+
* - explicit `baseUrl` + `apiKey` → a deliberate pin, used verbatim; the
|
|
74
|
+
* ambient chain is never consulted (hasna/apps#1794).
|
|
75
|
+
* - explicit `baseUrl` without `apiKey` → throws (no ambient key attach).
|
|
76
|
+
* - otherwise the @hasna/contracts chain resolves credential + authority, and
|
|
77
|
+
* every request re-resolves the KEY on a fresh snapshot while the AUTHORITY
|
|
78
|
+
* stays pinned (a changed authority is a new client, never a key sent to the
|
|
79
|
+
* wrong server). Any refusal throws — there is no local fallback.
|
|
80
|
+
*/
|
|
81
|
+
export declare function createContactsClient(options?: CreateContactsClientOptions): ContactsV1Client;
|
|
82
|
+
export { ContactsClientConfigurationError };
|
|
16
83
|
export { ApiError as ContactsV1ApiError };
|
|
17
84
|
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";
|
|
18
85
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/sdk/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAkD,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnH,OAAO,EAAE,gCAAgC,EAAkC,MAAM,0BAA0B,CAAC;AAC5G,OAAO,EAA+B,KAAK,GAAG,EAAE,MAAM,6BAA6B,CAAC;AACpF,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;+EAC2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4BD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,yBAAyB;gBACjD,OAAO,EAAE,uBAAuB;CAS7C;AAED,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,EAAG,UAAmB,CAAC;AAErD,gDAAgD;AAChD,MAAM,WAAW,2BACf,SAAQ,IAAI,CAAC,gCAAgC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpE;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC;AAED,mFAAmF;AACnF,wBAAgB,8BAA8B,IAAI,MAAM,CAMvD;AA0BD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,2BAAgC,GAAG,gBAAgB,CAiDhG;AAED,OAAO,EAAE,gCAAgC,EAAE,CAAC;AAC5C,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"}
|