@nsp-labs/agnostic-sdk 1.0.4 → 1.1.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/CHANGELOG.md +18 -0
- package/README.md +25 -5
- package/package.json +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -1
- package/src/lib/manifest.d.ts +39 -0
- package/src/lib/manifest.js +99 -0
- package/src/lib/runtime-client.d.ts +2 -0
- package/src/lib/runtime-client.js +36 -5
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,24 @@ and pass the runtime OpenAPI schema check.
|
|
|
9
9
|
|
|
10
10
|
## Unreleased
|
|
11
11
|
|
|
12
|
+
## 1.1.0 - 2026-07-26
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Added an exact public-surface drift guard and a deterministic manifest
|
|
17
|
+
fingerprint so Agent codegen can re-read the installed SDK contract on every
|
|
18
|
+
generation step instead of relying on a copied namespace list.
|
|
19
|
+
- Added `auth.getSession()` for optional App Auth sessions and
|
|
20
|
+
`auth.requireScopes()` for application-level scope guardrails after session
|
|
21
|
+
verification.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Runtime SDK manifest consumers can now derive scaffold versions, Agent review
|
|
26
|
+
allowlists, and source-write deny rules from the exported package contract.
|
|
27
|
+
The runtime OpenAPI schema is unchanged; the callable SDK surface adds only
|
|
28
|
+
the backwards-compatible App Auth helpers listed above.
|
|
29
|
+
|
|
12
30
|
## 1.0.4 - 2026-06-18
|
|
13
31
|
|
|
14
32
|
### Changed
|
package/README.md
CHANGED
|
@@ -46,13 +46,33 @@ the incoming App Auth session through the runtime helper:
|
|
|
46
46
|
```ts
|
|
47
47
|
const session = await agnostic.auth.requireSession(request);
|
|
48
48
|
|
|
49
|
-
await agnostic.data
|
|
50
|
-
'
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
await agnostic.data
|
|
50
|
+
.table('orders')
|
|
51
|
+
.records.update(
|
|
52
|
+
'order_123',
|
|
53
|
+
{ values: { status: 'fulfilled' } },
|
|
54
|
+
{ actor: session.actor },
|
|
55
|
+
);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Use `getSession(request)` for routes that support both guests and signed-in
|
|
59
|
+
users. It returns `null` when the request has no App Auth session:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const session = await agnostic.auth.getSession(request);
|
|
54
63
|
```
|
|
55
64
|
|
|
65
|
+
Use `requireScopes(request, scopes)` for application-level scope guardrails.
|
|
66
|
+
This verifies the session first and throws `app_auth_scope_missing` when one of
|
|
67
|
+
the required app-user scopes is absent:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const session = await agnostic.auth.requireScopes(request, ['orders:write']);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Scope checks do not replace ownership or other business rules in the
|
|
74
|
+
application backend.
|
|
75
|
+
|
|
56
76
|
The helper extracts `Authorization: Bearer <app-session>` or an
|
|
57
77
|
`agnostic_app_session_*` cookie, then calls
|
|
58
78
|
`/api/v1/runtime/app-auth/session/verify` with the server-side runtime token.
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AgnosticRuntime, RuntimeAppAuthNamespace, RuntimeContextNamespace, RuntimeDataNamespace, RuntimeDataRecordsClient, RuntimeDataTableClient, RuntimeDataViewClient, RuntimeDataViewTableClient, RuntimeWorkflowRunsNamespace, RuntimeWorkflowsNamespace, createAgnosticRuntime, } from './lib/runtime-client';
|
|
2
2
|
export { normalizeApiUrl, resolveRuntimeContext } from './lib/context';
|
|
3
3
|
export { AgnosticRuntimeError } from './lib/errors';
|
|
4
|
+
export { AGNOSTIC_RUNTIME_SDK_MANIFEST, type AgnosticRuntimeSdkManifest, } from './lib/manifest';
|
|
4
5
|
export type { AgnosticRuntimeConfig, ResolvedRuntimeContext, RuntimeActorMetadata, RuntimeActorType, RuntimeAppAuthActor, RuntimeAppAuthCachePolicy, RuntimeAppAuthRequestLike, RuntimeAppAuthSession, RuntimeAppAuthSessionClaims, RuntimeAppAuthUserClaims, RuntimeAppAuthUserResult, RuntimeCreateRecordInput, RuntimeDataField, RuntimeDataViewState, RuntimeIdentityContext, RuntimeListRecordsOptions, RuntimeListWindowOptions, RuntimeRecord, RuntimeRecordMutation, RuntimeRecordsList, RuntimeRequestOptions, RuntimeRowData, RuntimeRowValue, RuntimeTableWindow, RuntimeUpdateRecordInput, RuntimeWorkflowRun, RuntimeWorkflowStepRun, RuntimeWorkflowWaitOptions, WorkflowRunStatus, } from './lib/types';
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AgnosticRuntimeError = exports.resolveRuntimeContext = exports.normalizeApiUrl = exports.createAgnosticRuntime = exports.RuntimeWorkflowsNamespace = exports.RuntimeWorkflowRunsNamespace = exports.RuntimeDataViewTableClient = exports.RuntimeDataViewClient = exports.RuntimeDataTableClient = exports.RuntimeDataRecordsClient = exports.RuntimeDataNamespace = exports.RuntimeContextNamespace = exports.RuntimeAppAuthNamespace = exports.AgnosticRuntime = void 0;
|
|
3
|
+
exports.AGNOSTIC_RUNTIME_SDK_MANIFEST = exports.AgnosticRuntimeError = exports.resolveRuntimeContext = exports.normalizeApiUrl = exports.createAgnosticRuntime = exports.RuntimeWorkflowsNamespace = exports.RuntimeWorkflowRunsNamespace = exports.RuntimeDataViewTableClient = exports.RuntimeDataViewClient = exports.RuntimeDataTableClient = exports.RuntimeDataRecordsClient = exports.RuntimeDataNamespace = exports.RuntimeContextNamespace = exports.RuntimeAppAuthNamespace = exports.AgnosticRuntime = void 0;
|
|
4
4
|
var runtime_client_1 = require("./lib/runtime-client");
|
|
5
5
|
Object.defineProperty(exports, "AgnosticRuntime", { enumerable: true, get: function () { return runtime_client_1.AgnosticRuntime; } });
|
|
6
6
|
Object.defineProperty(exports, "RuntimeAppAuthNamespace", { enumerable: true, get: function () { return runtime_client_1.RuntimeAppAuthNamespace; } });
|
|
@@ -18,4 +18,6 @@ Object.defineProperty(exports, "normalizeApiUrl", { enumerable: true, get: funct
|
|
|
18
18
|
Object.defineProperty(exports, "resolveRuntimeContext", { enumerable: true, get: function () { return context_1.resolveRuntimeContext; } });
|
|
19
19
|
var errors_1 = require("./lib/errors");
|
|
20
20
|
Object.defineProperty(exports, "AgnosticRuntimeError", { enumerable: true, get: function () { return errors_1.AgnosticRuntimeError; } });
|
|
21
|
+
var manifest_1 = require("./lib/manifest");
|
|
22
|
+
Object.defineProperty(exports, "AGNOSTIC_RUNTIME_SDK_MANIFEST", { enumerable: true, get: function () { return manifest_1.AGNOSTIC_RUNTIME_SDK_MANIFEST; } });
|
|
21
23
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const AGNOSTIC_RUNTIME_SDK_MANIFEST: Readonly<{
|
|
2
|
+
readonly promptSync: Readonly<{
|
|
3
|
+
source: "sdk_exported_manifest";
|
|
4
|
+
strategy: "inject_on_every_agent_codegen_context";
|
|
5
|
+
surfaceFingerprint: string;
|
|
6
|
+
driftPolicy: "fail_ci_on_public_surface_or_package_version_mismatch";
|
|
7
|
+
memorizedSdkKnowledgeAllowed: false;
|
|
8
|
+
}>;
|
|
9
|
+
readonly schema: "agnostic_runtime_sdk_manifest.v1";
|
|
10
|
+
readonly package: Readonly<{
|
|
11
|
+
name: "@nsp-labs/agnostic-sdk";
|
|
12
|
+
version: "1.1.0";
|
|
13
|
+
factory: "createAgnosticRuntime";
|
|
14
|
+
runtime: "server_only";
|
|
15
|
+
}>;
|
|
16
|
+
readonly context: Readonly<{
|
|
17
|
+
automatic: true;
|
|
18
|
+
environmentVariables: readonly string[];
|
|
19
|
+
secretEnvironmentVariables: readonly string[];
|
|
20
|
+
}>;
|
|
21
|
+
readonly rootMembers: readonly [...("data" | "auth" | "context" | "workflows" | "workflowRuns")[], "getRuntimeContext"];
|
|
22
|
+
readonly clientMethods: readonly ["getRuntimeContext"];
|
|
23
|
+
readonly namespaces: Readonly<{
|
|
24
|
+
auth: readonly ("requireSession" | "getSession" | "requireScopes" | "getUser")[];
|
|
25
|
+
context: readonly "get"[];
|
|
26
|
+
data: readonly ("table(name).records.delete" | "table(name).records.list" | "table(name).records.create" | "table(name).records.update" | "view(id).table.window")[];
|
|
27
|
+
workflows: readonly ("start" | "getRun")[];
|
|
28
|
+
workflowRuns: readonly ("get" | "wait" | "listSteps")[];
|
|
29
|
+
}>;
|
|
30
|
+
readonly unsupportedNamespaces: readonly string[];
|
|
31
|
+
readonly boundaries: Readonly<{
|
|
32
|
+
controlPlaneProvisioning: "agent_product_tools";
|
|
33
|
+
runtimeAccess: "server_sdk";
|
|
34
|
+
browserAccess: "public_api_or_app_auth_session";
|
|
35
|
+
browserPackageImportAllowed: false;
|
|
36
|
+
browserRuntimeTokenAllowed: false;
|
|
37
|
+
}>;
|
|
38
|
+
}>;
|
|
39
|
+
export type AgnosticRuntimeSdkManifest = typeof AGNOSTIC_RUNTIME_SDK_MANIFEST;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AGNOSTIC_RUNTIME_SDK_MANIFEST = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const AUTH_KEYS_LITERAL = [
|
|
6
|
+
'requireSession',
|
|
7
|
+
'getSession',
|
|
8
|
+
'requireScopes',
|
|
9
|
+
'getUser',
|
|
10
|
+
];
|
|
11
|
+
const AUTH_KEYS = AUTH_KEYS_LITERAL;
|
|
12
|
+
const CONTEXT_KEYS_LITERAL = ['get'];
|
|
13
|
+
const CONTEXT_KEYS = CONTEXT_KEYS_LITERAL;
|
|
14
|
+
const DATA_NAMESPACE_KEYS_LITERAL = ['table', 'view'];
|
|
15
|
+
const DATA_NAMESPACE_KEYS = DATA_NAMESPACE_KEYS_LITERAL;
|
|
16
|
+
const DATA_TABLE_KEYS_LITERAL = ['records'];
|
|
17
|
+
const DATA_TABLE_KEYS = DATA_TABLE_KEYS_LITERAL;
|
|
18
|
+
const DATA_RECORD_KEYS_LITERAL = [
|
|
19
|
+
'list',
|
|
20
|
+
'create',
|
|
21
|
+
'update',
|
|
22
|
+
'delete',
|
|
23
|
+
];
|
|
24
|
+
const DATA_RECORD_KEYS = DATA_RECORD_KEYS_LITERAL;
|
|
25
|
+
const DATA_VIEW_KEYS_LITERAL = ['table'];
|
|
26
|
+
const DATA_VIEW_KEYS = DATA_VIEW_KEYS_LITERAL;
|
|
27
|
+
const DATA_VIEW_TABLE_KEYS_LITERAL = ['window'];
|
|
28
|
+
const DATA_VIEW_TABLE_KEYS = DATA_VIEW_TABLE_KEYS_LITERAL;
|
|
29
|
+
const WORKFLOW_KEYS_LITERAL = ['start', 'getRun'];
|
|
30
|
+
const WORKFLOW_KEYS = WORKFLOW_KEYS_LITERAL;
|
|
31
|
+
const WORKFLOW_RUN_KEYS_LITERAL = ['get', 'wait', 'listSteps'];
|
|
32
|
+
const WORKFLOW_RUN_KEYS = WORKFLOW_RUN_KEYS_LITERAL;
|
|
33
|
+
const CLIENT_METHODS = Object.freeze(['getRuntimeContext']);
|
|
34
|
+
const NAMESPACES = Object.freeze({
|
|
35
|
+
auth: Object.freeze([...AUTH_KEYS]),
|
|
36
|
+
context: Object.freeze([...CONTEXT_KEYS]),
|
|
37
|
+
data: Object.freeze([
|
|
38
|
+
...DATA_RECORD_KEYS.map((method) => `${DATA_NAMESPACE_KEYS[0]}(name).${DATA_TABLE_KEYS[0]}.${method}`),
|
|
39
|
+
...DATA_VIEW_TABLE_KEYS.map((method) => `${DATA_NAMESPACE_KEYS[1]}(id).${DATA_VIEW_KEYS[0]}.${method}`),
|
|
40
|
+
]),
|
|
41
|
+
workflows: Object.freeze([...WORKFLOW_KEYS]),
|
|
42
|
+
workflowRuns: Object.freeze([...WORKFLOW_RUN_KEYS]),
|
|
43
|
+
});
|
|
44
|
+
const ROOT_MEMBERS_LITERAL = Object.freeze([
|
|
45
|
+
...Object.keys(NAMESPACES),
|
|
46
|
+
...CLIENT_METHODS,
|
|
47
|
+
]);
|
|
48
|
+
const ROOT_MEMBERS = ROOT_MEMBERS_LITERAL;
|
|
49
|
+
const MANIFEST_CONTRACT = Object.freeze({
|
|
50
|
+
schema: 'agnostic_runtime_sdk_manifest.v1',
|
|
51
|
+
package: Object.freeze({
|
|
52
|
+
name: '@nsp-labs/agnostic-sdk',
|
|
53
|
+
version: '1.1.0',
|
|
54
|
+
factory: 'createAgnosticRuntime',
|
|
55
|
+
runtime: 'server_only',
|
|
56
|
+
}),
|
|
57
|
+
context: Object.freeze({
|
|
58
|
+
automatic: true,
|
|
59
|
+
environmentVariables: Object.freeze([
|
|
60
|
+
'AGNOSTIC_API_URL',
|
|
61
|
+
'AGNOSTIC_PROJECT_ID',
|
|
62
|
+
'AGNOSTIC_ENVIRONMENT',
|
|
63
|
+
'AGNOSTIC_RUNTIME_TOKEN',
|
|
64
|
+
]),
|
|
65
|
+
secretEnvironmentVariables: Object.freeze(['AGNOSTIC_RUNTIME_TOKEN']),
|
|
66
|
+
}),
|
|
67
|
+
rootMembers: ROOT_MEMBERS,
|
|
68
|
+
clientMethods: CLIENT_METHODS,
|
|
69
|
+
namespaces: NAMESPACES,
|
|
70
|
+
unsupportedNamespaces: Object.freeze([
|
|
71
|
+
'ai',
|
|
72
|
+
'events',
|
|
73
|
+
'gateway',
|
|
74
|
+
'jobs',
|
|
75
|
+
'realtime',
|
|
76
|
+
'storage',
|
|
77
|
+
]),
|
|
78
|
+
boundaries: Object.freeze({
|
|
79
|
+
controlPlaneProvisioning: 'agent_product_tools',
|
|
80
|
+
runtimeAccess: 'server_sdk',
|
|
81
|
+
browserAccess: 'public_api_or_app_auth_session',
|
|
82
|
+
browserPackageImportAllowed: false,
|
|
83
|
+
browserRuntimeTokenAllowed: false,
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
const surfaceFingerprint = `sha256:${(0, node_crypto_1.createHash)('sha256')
|
|
87
|
+
.update(JSON.stringify(MANIFEST_CONTRACT))
|
|
88
|
+
.digest('hex')}`;
|
|
89
|
+
exports.AGNOSTIC_RUNTIME_SDK_MANIFEST = Object.freeze({
|
|
90
|
+
...MANIFEST_CONTRACT,
|
|
91
|
+
promptSync: Object.freeze({
|
|
92
|
+
source: 'sdk_exported_manifest',
|
|
93
|
+
strategy: 'inject_on_every_agent_codegen_context',
|
|
94
|
+
surfaceFingerprint,
|
|
95
|
+
driftPolicy: 'fail_ci_on_public_surface_or_package_version_mismatch',
|
|
96
|
+
memorizedSdkKnowledgeAllowed: false,
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -15,6 +15,8 @@ export declare class RuntimeAppAuthNamespace {
|
|
|
15
15
|
private readonly openapi;
|
|
16
16
|
constructor(openapi: RuntimeOpenApiClient);
|
|
17
17
|
requireSession(request: RuntimeAppAuthRequestLike | string, options?: RuntimeRequestOptions): Promise<RuntimeAppAuthSession>;
|
|
18
|
+
getSession(request: RuntimeAppAuthRequestLike | string, options?: RuntimeRequestOptions): Promise<RuntimeAppAuthSession | null>;
|
|
19
|
+
requireScopes(request: RuntimeAppAuthRequestLike | string, scopes: readonly string[], options?: RuntimeRequestOptions): Promise<RuntimeAppAuthSession>;
|
|
18
20
|
getUser(userId: string, options?: RuntimeRequestOptions): Promise<RuntimeAppAuthUserResult>;
|
|
19
21
|
}
|
|
20
22
|
export declare function createAgnosticRuntime(config?: AgnosticRuntimeConfig): AgnosticRuntime;
|
|
@@ -58,11 +58,35 @@ class RuntimeAppAuthNamespace {
|
|
|
58
58
|
},
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
return verifyAppAuthSession(this.openapi, sessionToken, options);
|
|
62
|
+
}
|
|
63
|
+
async getSession(request, options) {
|
|
64
|
+
const sessionToken = typeof request === 'string'
|
|
65
|
+
? normalizeSessionToken(request)
|
|
66
|
+
: extractAppSessionToken(request);
|
|
67
|
+
if (!sessionToken) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return verifyAppAuthSession(this.openapi, sessionToken, options);
|
|
71
|
+
}
|
|
72
|
+
async requireScopes(request, scopes, options) {
|
|
73
|
+
const session = await this.requireSession(request, options);
|
|
74
|
+
const requiredScopes = Array.from(new Set(scopes.map((scope) => scope.trim()).filter(Boolean)));
|
|
75
|
+
const availableScopes = new Set(session.user.scopes);
|
|
76
|
+
const missingScopes = requiredScopes.filter((scope) => !availableScopes.has(scope));
|
|
77
|
+
if (missingScopes.length > 0) {
|
|
78
|
+
throw new errors_1.AgnosticRuntimeError({
|
|
79
|
+
status: 403,
|
|
80
|
+
code: 'app_auth_scope_missing',
|
|
81
|
+
message: 'App user is missing a required scope',
|
|
82
|
+
details: {
|
|
83
|
+
availableScopes: session.user.scopes,
|
|
84
|
+
missingScopes,
|
|
85
|
+
requiredScopes,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return session;
|
|
66
90
|
}
|
|
67
91
|
async getUser(userId, options) {
|
|
68
92
|
const result = await this.openapi.GET(APP_AUTH_USER_PATH, {
|
|
@@ -78,6 +102,13 @@ exports.RuntimeAppAuthNamespace = RuntimeAppAuthNamespace;
|
|
|
78
102
|
function createAgnosticRuntime(config = {}) {
|
|
79
103
|
return new AgnosticRuntime(config);
|
|
80
104
|
}
|
|
105
|
+
async function verifyAppAuthSession(openapi, sessionToken, options) {
|
|
106
|
+
const result = await openapi.POST(APP_AUTH_VERIFY_SESSION_PATH, {
|
|
107
|
+
body: { sessionToken },
|
|
108
|
+
headers: (0, http_client_1.runtimeRequestHeaders)(options),
|
|
109
|
+
});
|
|
110
|
+
return (0, http_client_1.unwrapRuntimeResult)(result, 'Failed to verify App Auth session');
|
|
111
|
+
}
|
|
81
112
|
class RuntimeContextNamespace {
|
|
82
113
|
constructor(openapi) {
|
|
83
114
|
this.openapi = openapi;
|