@abloatai/ablo 0.9.14 → 0.9.15
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 +6 -0
- package/dist/Model.js +9 -1
- package/dist/environment.d.ts +12 -0
- package/dist/environment.js +16 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/keys/index.d.ts +6 -3
- package/dist/keys/index.js +14 -5
- package/dist/transactions/TransactionQueue.js +6 -0
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.15
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Package metadata: set the npm description to "The Collaboration Layer For AI Agents" (matching the GitHub repo About) so it stops reverting to the old "State control API…" text on publish.
|
|
8
|
+
|
|
3
9
|
## 0.9.14
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/dist/Model.js
CHANGED
|
@@ -78,11 +78,19 @@ export class Model {
|
|
|
78
78
|
? data.createdAt
|
|
79
79
|
: new Date(data.createdAt)
|
|
80
80
|
: new Date();
|
|
81
|
+
// A record that arrives WITH `createdAt` but WITHOUT `updatedAt` is
|
|
82
|
+
// server/IDB data whose update timestamp didn't survive the wire —
|
|
83
|
+
// falling back to "now" here fabricated an edit time for every such
|
|
84
|
+
// record on every bootstrap (the decks gallery sorted everything to
|
|
85
|
+
// "edited just now"). Fall back to createdAt instead; only a genuinely
|
|
86
|
+
// new local model (no dates at all) stamps the current time.
|
|
81
87
|
this.updatedAt = data.updatedAt
|
|
82
88
|
? data.updatedAt instanceof Date
|
|
83
89
|
? data.updatedAt
|
|
84
90
|
: new Date(data.updatedAt)
|
|
85
|
-
:
|
|
91
|
+
: data.createdAt
|
|
92
|
+
? new Date(this.createdAt)
|
|
93
|
+
: new Date();
|
|
86
94
|
this.syncStatus = data.syncStatus || 'pending';
|
|
87
95
|
}
|
|
88
96
|
/**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ENVIRONMENTS: readonly ["production", "sandbox"];
|
|
3
|
+
export type KeyPrefixEnvironment = 'live' | 'test';
|
|
4
|
+
export declare const environmentSchema: z.ZodEnum<{
|
|
5
|
+
production: "production";
|
|
6
|
+
sandbox: "sandbox";
|
|
7
|
+
}>;
|
|
8
|
+
export type Environment = z.infer<typeof environmentSchema>;
|
|
9
|
+
export declare function normalizeEnvironment(value: unknown, fallback?: Environment): Environment;
|
|
10
|
+
export declare function environmentFromKeyPrefix(value: KeyPrefixEnvironment): Environment;
|
|
11
|
+
export declare function environmentToKeyPrefix(value: Environment): KeyPrefixEnvironment;
|
|
12
|
+
export declare function isSandboxEnvironment(value: Environment): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const ENVIRONMENTS = ['production', 'sandbox'];
|
|
3
|
+
export const environmentSchema = z.enum(ENVIRONMENTS);
|
|
4
|
+
export function normalizeEnvironment(value, fallback = 'production') {
|
|
5
|
+
const parsed = environmentSchema.safeParse(value);
|
|
6
|
+
return parsed.success ? parsed.data : fallback;
|
|
7
|
+
}
|
|
8
|
+
export function environmentFromKeyPrefix(value) {
|
|
9
|
+
return value === 'test' ? 'sandbox' : 'production';
|
|
10
|
+
}
|
|
11
|
+
export function environmentToKeyPrefix(value) {
|
|
12
|
+
return value === 'sandbox' ? 'test' : 'live';
|
|
13
|
+
}
|
|
14
|
+
export function isSandboxEnvironment(value) {
|
|
15
|
+
return value === 'sandbox';
|
|
16
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -64,6 +64,8 @@ export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionErr
|
|
|
64
64
|
export type { CommitReceipt, RequiredCapability } from './errors.js';
|
|
65
65
|
export type { ErrorCode, WireErrorCode, ErrorCategory, ErrorCodeSpec, RecoveryClass } from './errors.js';
|
|
66
66
|
export { WS_BEARER_SUBPROTOCOL_PREFIX, WS_SYNC_SUBPROTOCOL } from './auth/credentialSource.js';
|
|
67
|
+
export { ENVIRONMENTS, environmentSchema, normalizeEnvironment, environmentFromKeyPrefix, environmentToKeyPrefix, isSandboxEnvironment, } from './environment.js';
|
|
68
|
+
export type { Environment, KeyPrefixEnvironment } from './environment.js';
|
|
67
69
|
export { writeOptionsSchema, onStaleModeSchema, assertWriteOptions, } from './client/writeOptionsSchema.js';
|
|
68
70
|
export type { WriteOptionsInput } from './client/writeOptionsSchema.js';
|
|
69
71
|
export type { WriteOptions, MutationOptions } from './interfaces/index.js';
|
package/dist/index.js
CHANGED
|
@@ -89,6 +89,7 @@ export { defaultPolicy, capabilityPreemptPolicy } from './policy/index.js';
|
|
|
89
89
|
// `e.type === 'AbloX'`) plus the HTTP-response translator.
|
|
90
90
|
export { SyncSessionError, AbloError, AbloAuthenticationError, AbloPermissionError, AbloRateLimitError, AbloIdempotencyError, AbloConnectionError, AbloValidationError, AbloServerError, AbloStaleContextError, AbloClaimedError, CapabilityError, translateHttpError, hasWireCode, errorFromWire, toAbloError, ERROR_CODES, ERROR_CONTRACT_VERSION, errorCodeSpec, isRetryableCode, classifyRecovery, recoveryClassSchema, RECOVERY_CLASSES, } from './errors.js';
|
|
91
91
|
export { WS_BEARER_SUBPROTOCOL_PREFIX, WS_SYNC_SUBPROTOCOL } from './auth/credentialSource.js';
|
|
92
|
+
export { ENVIRONMENTS, environmentSchema, normalizeEnvironment, environmentFromKeyPrefix, environmentToKeyPrefix, isSandboxEnvironment, } from './environment.js';
|
|
92
93
|
// THE write-options contract — the one Zod schema for the option bag every
|
|
93
94
|
// write door accepts (`ablo.<model>.create/update/delete`, `commits.create`,
|
|
94
95
|
// the HTTP model routes). The SDK validates against it at each boundary;
|
package/dist/keys/index.d.ts
CHANGED
|
@@ -10,16 +10,19 @@
|
|
|
10
10
|
* client bundle never pulls in `node:crypto`.
|
|
11
11
|
*
|
|
12
12
|
* Format (GitHub-style): `<sk|rk|ek>_<live|test>_<30 base62 body><6-char
|
|
13
|
-
* base62 CRC32 checksum>`. The
|
|
13
|
+
* base62 CRC32 checksum>`. The environment segment is the stable key-prefix
|
|
14
|
+
* contract; parsed values are immediately mapped to `production` / `sandbox`.
|
|
15
|
+
* The identifiable prefix + CRC32 checksum let
|
|
14
16
|
* secret scanners detect leaks and let us reject typo'd/forged keys OFFLINE
|
|
15
17
|
* (no DB round-trip). Legacy keys (a ~43-char base64url body, no checksum)
|
|
16
18
|
* still validate by hash — they parse here as `checksummed: false`.
|
|
17
19
|
*/
|
|
18
20
|
import { z } from 'zod';
|
|
21
|
+
import { type Environment } from '../environment.js';
|
|
19
22
|
export declare const API_KEY_KINDS: readonly ["secret", "restricted", "ephemeral", "publishable"];
|
|
20
23
|
export type ApiKeyKind = (typeof API_KEY_KINDS)[number];
|
|
21
|
-
export declare const API_KEY_ENVS: readonly ["
|
|
22
|
-
export type ApiKeyEnv =
|
|
24
|
+
export declare const API_KEY_ENVS: readonly ["production", "sandbox"];
|
|
25
|
+
export type ApiKeyEnv = Environment;
|
|
23
26
|
/** A structurally-valid Ablo API key, parsed into its parts. */
|
|
24
27
|
export interface ParsedApiKey {
|
|
25
28
|
/** The original plaintext. */
|
package/dist/keys/index.js
CHANGED
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
* client bundle never pulls in `node:crypto`.
|
|
11
11
|
*
|
|
12
12
|
* Format (GitHub-style): `<sk|rk|ek>_<live|test>_<30 base62 body><6-char
|
|
13
|
-
* base62 CRC32 checksum>`. The
|
|
13
|
+
* base62 CRC32 checksum>`. The environment segment is the stable key-prefix
|
|
14
|
+
* contract; parsed values are immediately mapped to `production` / `sandbox`.
|
|
15
|
+
* The identifiable prefix + CRC32 checksum let
|
|
14
16
|
* secret scanners detect leaks and let us reject typo'd/forged keys OFFLINE
|
|
15
17
|
* (no DB round-trip). Legacy keys (a ~43-char base64url body, no checksum)
|
|
16
18
|
* still validate by hash — they parse here as `checksummed: false`.
|
|
17
19
|
*/
|
|
18
20
|
import { createHash, randomBytes } from 'node:crypto';
|
|
19
21
|
import { z } from 'zod';
|
|
22
|
+
import { ENVIRONMENTS, environmentFromKeyPrefix, environmentToKeyPrefix, } from '../environment.js';
|
|
20
23
|
// ── Vocabulary ──────────────────────────────────────────────────────────
|
|
21
24
|
// The Stripe-style key model:
|
|
22
25
|
// secret (sk_) — backend / server-to-server / agents. Full authority. Never in a browser.
|
|
@@ -29,7 +32,7 @@ import { z } from 'zod';
|
|
|
29
32
|
// it; it grants read access to the org's data plane and cannot write
|
|
30
33
|
// or reach any control-plane operation.
|
|
31
34
|
export const API_KEY_KINDS = ['secret', 'restricted', 'ephemeral', 'publishable'];
|
|
32
|
-
export const API_KEY_ENVS =
|
|
35
|
+
export const API_KEY_ENVS = ENVIRONMENTS;
|
|
33
36
|
const PREFIX_BY_KIND = {
|
|
34
37
|
secret: 'sk',
|
|
35
38
|
restricted: 'rk',
|
|
@@ -115,7 +118,13 @@ export const apiKeySchema = z.string().transform((raw, ctx) => {
|
|
|
115
118
|
ctx.addIssue({ code: 'custom', message: 'API key checksum mismatch' });
|
|
116
119
|
return z.NEVER;
|
|
117
120
|
}
|
|
118
|
-
return {
|
|
121
|
+
return {
|
|
122
|
+
raw,
|
|
123
|
+
kind: KIND_BY_PREFIX[prefix],
|
|
124
|
+
env: environmentFromKeyPrefix(env),
|
|
125
|
+
body,
|
|
126
|
+
checksummed,
|
|
127
|
+
};
|
|
119
128
|
});
|
|
120
129
|
// ── Derived validators (thin wrappers over the same spec) ───────────────
|
|
121
130
|
/** Parse + fully validate (incl. checksum). Returns null when invalid. */
|
|
@@ -140,9 +149,9 @@ export function keyChecksumMatches(raw) {
|
|
|
140
149
|
* Mint a key: `<prefix>_<env>_<body><checksum>`. Returns the plaintext (shown
|
|
141
150
|
* once), its SHA-256 hash (persisted), and the 12-char display prefix.
|
|
142
151
|
*/
|
|
143
|
-
export function generateApiKey(env = '
|
|
152
|
+
export function generateApiKey(env = 'production', kind = 'secret') {
|
|
144
153
|
const body = randomBase62(KEY_BODY_LEN);
|
|
145
|
-
const payload = `${PREFIX_BY_KIND[kind]}_${env}_${body}`;
|
|
154
|
+
const payload = `${PREFIX_BY_KIND[kind]}_${environmentToKeyPrefix(env)}_${body}`;
|
|
146
155
|
const plaintext = `${payload}${checksum6(payload)}`;
|
|
147
156
|
return { plaintext, hash: hashApiKey(plaintext), prefix: plaintext.slice(0, 12) };
|
|
148
157
|
}
|
|
@@ -949,6 +949,12 @@ export class TransactionQueue extends EventEmitter {
|
|
|
949
949
|
// Ensure derived fields exist (covers restored/persisted transactions)
|
|
950
950
|
this.ensureDerivedFields(a);
|
|
951
951
|
this.ensureDerivedFields(b);
|
|
952
|
+
if (a.modelName === b.modelName && a.modelId === b.modelId && a.type !== b.type) {
|
|
953
|
+
if (a.type === 'create')
|
|
954
|
+
return -1;
|
|
955
|
+
if (b.type === 'create')
|
|
956
|
+
return 1;
|
|
957
|
+
}
|
|
952
958
|
return a.priorityScore - b.priorityScore;
|
|
953
959
|
});
|
|
954
960
|
// Get batch (now guaranteed to have parent entities before children)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abloatai/ablo",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.9.15",
|
|
4
|
+
"description": "The Collaboration Layer For AI Agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -83,6 +83,11 @@
|
|
|
83
83
|
"import": "./dist/keys/index.js",
|
|
84
84
|
"default": "./dist/keys/index.js"
|
|
85
85
|
},
|
|
86
|
+
"./environment": {
|
|
87
|
+
"types": "./dist/environment.d.ts",
|
|
88
|
+
"import": "./dist/environment.js",
|
|
89
|
+
"default": "./dist/environment.js"
|
|
90
|
+
},
|
|
86
91
|
"./wire": {
|
|
87
92
|
"types": "./dist/wire/index.d.ts",
|
|
88
93
|
"import": "./dist/wire/index.js",
|