@agentxm/registry-auth 0.28.12 → 0.28.13
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/src/auth-client.d.ts +1 -1
- package/dist/src/auth-client.js +1 -1
- package/dist/src/credential-store.d.ts +39 -2
- package/dist/src/credential-store.js +50 -46
- package/dist/src/device-login.d.ts +2 -2
- package/dist/src/errors.d.ts +26 -2
- package/dist/src/errors.js +17 -0
- package/dist/src/identity.d.ts +46 -0
- package/dist/src/identity.js +49 -0
- package/dist/src/index.d.ts +10 -1
- package/dist/src/index.js +13 -1
- package/dist/src/internal/environment.d.ts +23 -5
- package/dist/src/internal/environment.js +59 -9
- package/dist/src/login-presenter.d.ts +55 -0
- package/dist/src/login-presenter.js +22 -0
- package/dist/src/login-suggestion.d.ts +18 -0
- package/dist/src/login-suggestion.js +34 -0
- package/dist/src/login.d.ts +80 -0
- package/dist/src/login.js +155 -0
- package/dist/src/logout.d.ts +35 -0
- package/dist/src/logout.js +37 -0
- package/dist/src/selected-registry.d.ts +25 -0
- package/dist/src/selected-registry.js +18 -0
- package/dist/src/step-up.d.ts +49 -0
- package/dist/src/step-up.js +174 -0
- package/dist/src/tokens.d.ts +57 -0
- package/dist/src/tokens.js +78 -0
- package/package.json +7 -6
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step-up verification: the protocol that carries one challenged Registry
|
|
3
|
+
* write through human verification and retries it exactly once.
|
|
4
|
+
*
|
|
5
|
+
* The capability owns challenge detection, request-reference validation,
|
|
6
|
+
* resumption and terminal-status rules, expiry, the bounded wait, and the
|
|
7
|
+
* retry-once contract. The application supplies only presentation and browser
|
|
8
|
+
* launch through the login presenter and interaction ports.
|
|
9
|
+
*
|
|
10
|
+
* @experimental This API is unstable and may change without notice.
|
|
11
|
+
*/
|
|
12
|
+
import * as Clock from "effect/Clock";
|
|
13
|
+
import * as DateTime from "effect/DateTime";
|
|
14
|
+
import * as Duration from "effect/Duration";
|
|
15
|
+
import * as Effect from "effect/Effect";
|
|
16
|
+
import * as Option from "effect/Option";
|
|
17
|
+
import * as Result from "effect/Result";
|
|
18
|
+
import { isRegistryClientFailure } from "@agentxm/registry-client";
|
|
19
|
+
import { AuthClient, readStepUpRequest } from "./auth-client.js";
|
|
20
|
+
import { CredentialStore } from "./credential-store.js";
|
|
21
|
+
import { authLoginRequired, RegistryAuthFailed, StepUpRequired, StepUpVerificationPending, } from "./errors.js";
|
|
22
|
+
import { AuthLoginInteraction } from "./login-interaction.js";
|
|
23
|
+
import { AuthLoginPresenter } from "./login-presenter.js";
|
|
24
|
+
import { resolveRequiredToken } from "./token-resolution.js";
|
|
25
|
+
const invalidReference = (detail, recover) => new RegistryAuthFailed({
|
|
26
|
+
category: "validation",
|
|
27
|
+
detail,
|
|
28
|
+
...(recover === undefined ? {} : { recover }),
|
|
29
|
+
});
|
|
30
|
+
/** Request references may only address the selected Registry's step-up resource. */
|
|
31
|
+
const readRequestReference = (reference, registryUrl) => Effect.try({
|
|
32
|
+
try: () => {
|
|
33
|
+
const url = new URL(reference);
|
|
34
|
+
const registry = new URL(registryUrl);
|
|
35
|
+
const match = /^\/v1\/auth\/step-up\/requests\/(step_[a-z0-9]+)$/.exec(url.pathname);
|
|
36
|
+
if (url.origin !== registry.origin ||
|
|
37
|
+
url.username ||
|
|
38
|
+
url.password ||
|
|
39
|
+
url.search ||
|
|
40
|
+
url.hash ||
|
|
41
|
+
match?.[1] === undefined)
|
|
42
|
+
throw new Error("Invalid step-up reference");
|
|
43
|
+
return match[1];
|
|
44
|
+
},
|
|
45
|
+
catch: () => invalidReference("The step-up request URL must identify a step-up request on the selected Registry.", "Use the requestRef from this Registry's pending-human result."),
|
|
46
|
+
});
|
|
47
|
+
const pendingVerification = (stepUp, registryUrl, timedOut) => new StepUpVerificationPending({
|
|
48
|
+
timedOut,
|
|
49
|
+
action: {
|
|
50
|
+
kind: "open-url",
|
|
51
|
+
purpose: "step-up",
|
|
52
|
+
requestRef: stepUp.statusUrl,
|
|
53
|
+
registryUrl,
|
|
54
|
+
url: stepUp.verificationUrl,
|
|
55
|
+
expiresAt: stepUp.expiresAt,
|
|
56
|
+
intervalSeconds: stepUp.intervalSeconds,
|
|
57
|
+
resume: `Rerun the same command with the same inputs and --step-up-request ${stepUp.statusUrl}. Add --wait-for-human SECONDS for a bounded wait.`,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
/** The challenge a failure carries, whether typed or still on the wire. */
|
|
61
|
+
const challengeOf = (failure) => failure instanceof StepUpRequired
|
|
62
|
+
? failure.stepUp
|
|
63
|
+
: isRegistryClientFailure(failure)
|
|
64
|
+
? readStepUpRequest(failure)
|
|
65
|
+
: null;
|
|
66
|
+
/**
|
|
67
|
+
* Run a Registry write that may be challenged, carry the challenge through
|
|
68
|
+
* human verification, and retry the write exactly once with the verified
|
|
69
|
+
* request id.
|
|
70
|
+
*
|
|
71
|
+
* The write is never replayed without verification, and a wait that elapses
|
|
72
|
+
* while the request is still valid resolves to `StepUpVerificationPending`
|
|
73
|
+
* rather than a failure of the write.
|
|
74
|
+
*/
|
|
75
|
+
export const runWithStepUp = (operation, presentation, options, registryUrl) => Effect.gen(function* () {
|
|
76
|
+
const authClient = yield* AuthClient;
|
|
77
|
+
const interaction = yield* AuthLoginInteraction;
|
|
78
|
+
const presenter = yield* AuthLoginPresenter;
|
|
79
|
+
const waitSeconds = options.waitForHumanSeconds;
|
|
80
|
+
if (waitSeconds !== undefined && (!Number.isSafeInteger(waitSeconds) || waitSeconds <= 0)) {
|
|
81
|
+
return yield* invalidReference("--wait-for-human must be a positive number of seconds.");
|
|
82
|
+
}
|
|
83
|
+
const resumedId = options.resumeReference === undefined
|
|
84
|
+
? undefined
|
|
85
|
+
: yield* readRequestReference(options.resumeReference, registryUrl);
|
|
86
|
+
const initial = resumedId === undefined
|
|
87
|
+
? yield* presenter.withProgress({ _tag: "RunningVerifiedWrite", operation: presentation.operationLabel }, () => Effect.result(operation()))
|
|
88
|
+
: undefined;
|
|
89
|
+
if (initial !== undefined && Result.isSuccess(initial)) {
|
|
90
|
+
return { value: initial.success, stepUpCompleted: false };
|
|
91
|
+
}
|
|
92
|
+
const challenge = initial !== undefined && Result.isFailure(initial) ? challengeOf(initial.failure) : null;
|
|
93
|
+
if (initial !== undefined && Result.isFailure(initial) && challenge === null) {
|
|
94
|
+
return yield* Effect.fail(initial.failure);
|
|
95
|
+
}
|
|
96
|
+
const token = yield* resolveRequiredToken(registryUrl, {
|
|
97
|
+
missingTokenError: authLoginRequired("Not authenticated"),
|
|
98
|
+
});
|
|
99
|
+
const resumed = resumedId === undefined
|
|
100
|
+
? undefined
|
|
101
|
+
: yield* authClient.getStepUpRequest(token.token, resumedId);
|
|
102
|
+
if (resumed !== undefined && resumed.status !== "pending" && resumed.status !== "verified") {
|
|
103
|
+
return yield* new RegistryAuthFailed({
|
|
104
|
+
category: resumed.status === "expired"
|
|
105
|
+
? "auth_expired"
|
|
106
|
+
: resumed.status === "cancelled"
|
|
107
|
+
? "auth_denied"
|
|
108
|
+
: "conflict",
|
|
109
|
+
detail: `The step-up request is ${resumed.status}. It cannot be resumed.`,
|
|
110
|
+
recover: "Review the result of the previous request before explicitly starting a new command without --step-up-request.",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const stepUp = challenge ??
|
|
114
|
+
(resumed !== undefined && resumedId !== undefined
|
|
115
|
+
? {
|
|
116
|
+
requestId: resumedId,
|
|
117
|
+
statusUrl: new URL(`/v1/auth/step-up/requests/${resumedId}`, registryUrl).href,
|
|
118
|
+
verificationUrl: new URL(`/step-up/${resumedId}`, authClient.getAuthorizationIssuer())
|
|
119
|
+
.href,
|
|
120
|
+
expiresAt: DateTime.formatIso(resumed.expires_at),
|
|
121
|
+
intervalSeconds: 2,
|
|
122
|
+
action: presentation.operationLabel,
|
|
123
|
+
target: presentation.operationLabel,
|
|
124
|
+
}
|
|
125
|
+
: null);
|
|
126
|
+
if (stepUp === null) {
|
|
127
|
+
return yield* new RegistryAuthFailed({
|
|
128
|
+
category: "auth",
|
|
129
|
+
detail: "The Registry did not return a verification request.",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const challengeId = yield* readRequestReference(stepUp.statusUrl, registryUrl);
|
|
133
|
+
if (challengeId !== stepUp.requestId) {
|
|
134
|
+
return yield* invalidReference("The Registry returned mismatched step-up references.");
|
|
135
|
+
}
|
|
136
|
+
const now = yield* Clock.currentTimeMillis;
|
|
137
|
+
const remaining = Date.parse(stepUp.expiresAt) - now;
|
|
138
|
+
if (!Number.isFinite(remaining) || remaining <= 0) {
|
|
139
|
+
return yield* new RegistryAuthFailed({
|
|
140
|
+
category: "auth_expired",
|
|
141
|
+
detail: "The step-up request has expired.",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (resumed?.status !== "verified") {
|
|
145
|
+
if (options.unattended && waitSeconds === undefined) {
|
|
146
|
+
return yield* pendingVerification(stepUp, registryUrl, false);
|
|
147
|
+
}
|
|
148
|
+
const opened = options.unattended
|
|
149
|
+
? false
|
|
150
|
+
: yield* interaction.openBrowser(stepUp.verificationUrl);
|
|
151
|
+
yield* presenter.presentStepUpChallenge({
|
|
152
|
+
action: stepUp.action,
|
|
153
|
+
target: stepUp.target,
|
|
154
|
+
verificationUrl: stepUp.verificationUrl,
|
|
155
|
+
expiresAt: stepUp.expiresAt,
|
|
156
|
+
browserOpened: opened,
|
|
157
|
+
});
|
|
158
|
+
const waited = yield* presenter.withProgress({ _tag: "WaitingForHumanVerification", operation: presentation.waitingLabel }, () => authClient
|
|
159
|
+
.waitForStepUpRequest(token.token, stepUp.statusUrl, stepUp.intervalSeconds)
|
|
160
|
+
.pipe(Effect.timeoutOption(Duration.millis(Math.min(remaining, waitSeconds === undefined ? remaining : waitSeconds * 1000)))));
|
|
161
|
+
if (Option.isNone(waited)) {
|
|
162
|
+
if ((yield* Clock.currentTimeMillis) >= Date.parse(stepUp.expiresAt)) {
|
|
163
|
+
return yield* new RegistryAuthFailed({
|
|
164
|
+
category: "auth_expired",
|
|
165
|
+
detail: "The step-up request has expired.",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return yield* pendingVerification(stepUp, registryUrl, true);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const value = yield* presenter.withProgress({ _tag: "RetryingVerifiedWrite", operation: presentation.operationLabel }, () => operation(stepUp.requestId));
|
|
172
|
+
return { value, stepUpCompleted: true };
|
|
173
|
+
});
|
|
174
|
+
//# sourceMappingURL=step-up.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Granular access-token policy: the expiry grammar and its bounds, the
|
|
3
|
+
* permission payload the Registry accepts, and the human-verification
|
|
4
|
+
* requirement on every token write.
|
|
5
|
+
*
|
|
6
|
+
* @experimental This API is unstable and may change without notice.
|
|
7
|
+
*/
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import * as Option from "effect/Option";
|
|
10
|
+
import { AuthClient, type CreatedTokenResponse, type TokenPermissionsRequest } from "./auth-client.js";
|
|
11
|
+
import { CredentialStore } from "./credential-store.js";
|
|
12
|
+
import { RegistryAuthFailed } from "./errors.js";
|
|
13
|
+
import { AuthLoginPresenter } from "./login-presenter.js";
|
|
14
|
+
import { type StepUpOptions } from "./step-up.js";
|
|
15
|
+
/** A token may live no less than an hour and no more than a year. */
|
|
16
|
+
export declare const MIN_TOKEN_LIFETIME_SECONDS = 3600;
|
|
17
|
+
export declare const MAX_TOKEN_LIFETIME_SECONDS = 31536000;
|
|
18
|
+
/** The authority a new token carries. */
|
|
19
|
+
export interface TokenAuthorityRequest {
|
|
20
|
+
readonly owners: ReadonlyArray<string>;
|
|
21
|
+
readonly extensions: ReadonlyArray<string>;
|
|
22
|
+
readonly permission: Option.Option<"read" | "publish" | "admin">;
|
|
23
|
+
readonly orgPermission: Option.Option<"read" | "write" | "admin">;
|
|
24
|
+
readonly cidr: ReadonlyArray<string>;
|
|
25
|
+
readonly bypassMfa: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface CreateTokenRequest extends TokenAuthorityRequest {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
/** Relative lifetime (`7d`, `30d`, `1y`) or an absolute ISO timestamp. */
|
|
30
|
+
readonly expires: string;
|
|
31
|
+
readonly verification: StepUpOptions;
|
|
32
|
+
}
|
|
33
|
+
export interface CreatedToken {
|
|
34
|
+
readonly token: CreatedTokenResponse;
|
|
35
|
+
readonly stepUpCompleted: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Read the requested lifetime. Relative forms are exact multiples; an
|
|
39
|
+
* absolute timestamp becomes the distance from now.
|
|
40
|
+
*/
|
|
41
|
+
export declare const parseExpiresInSeconds: (raw: string) => Effect.Effect<number, RegistryAuthFailed>;
|
|
42
|
+
/** Enforce the accepted lifetime window. */
|
|
43
|
+
export declare const validateExpiresInSeconds: (expiresIn: number) => Effect.Effect<number, RegistryAuthFailed>;
|
|
44
|
+
/** Only the authority a caller actually asked for reaches the Registry. */
|
|
45
|
+
export declare const tokenPermissions: (request: TokenAuthorityRequest) => TokenPermissionsRequest;
|
|
46
|
+
export declare const createToken: (request: CreateTokenRequest, registryUrl: string) => Effect.Effect<{
|
|
47
|
+
token: CreatedTokenResponse;
|
|
48
|
+
stepUpCompleted: boolean;
|
|
49
|
+
}, import("./errors.js").AuthError, AuthClient | CredentialStore | AuthLoginPresenter | import("./login-interaction.ts").AuthLoginInteraction>;
|
|
50
|
+
export declare const revokeToken: (tokenId: string, verification: StepUpOptions, registryUrl: string) => Effect.Effect<{
|
|
51
|
+
tokenId: string;
|
|
52
|
+
stepUpCompleted: boolean;
|
|
53
|
+
}, import("./errors.js").AuthError, AuthClient | CredentialStore | AuthLoginPresenter | import("./login-interaction.ts").AuthLoginInteraction>;
|
|
54
|
+
export declare const listTokens: (registryUrl: string) => Effect.Effect<import("./auth-client.js").TokenListResponse, import("./errors.js").AuthError, AuthClient | CredentialStore | AuthLoginPresenter>;
|
|
55
|
+
/** Declared for the reader; every member keeps these in `R`. */
|
|
56
|
+
export type TokenRequirements = AuthClient | CredentialStore | AuthLoginPresenter;
|
|
57
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Granular access-token policy: the expiry grammar and its bounds, the
|
|
3
|
+
* permission payload the Registry accepts, and the human-verification
|
|
4
|
+
* requirement on every token write.
|
|
5
|
+
*
|
|
6
|
+
* @experimental This API is unstable and may change without notice.
|
|
7
|
+
*/
|
|
8
|
+
import * as DateTime from "effect/DateTime";
|
|
9
|
+
import * as Duration from "effect/Duration";
|
|
10
|
+
import * as Effect from "effect/Effect";
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import { AuthClient, } from "./auth-client.js";
|
|
13
|
+
import { CredentialStore } from "./credential-store.js";
|
|
14
|
+
import { RegistryAuthFailed } from "./errors.js";
|
|
15
|
+
import { AuthLoginPresenter } from "./login-presenter.js";
|
|
16
|
+
import { currentToken } from "./identity.js";
|
|
17
|
+
import { runWithStepUp } from "./step-up.js";
|
|
18
|
+
/** A token may live no less than an hour and no more than a year. */
|
|
19
|
+
export const MIN_TOKEN_LIFETIME_SECONDS = 3_600;
|
|
20
|
+
export const MAX_TOKEN_LIFETIME_SECONDS = 31_536_000;
|
|
21
|
+
const invalid = (detail) => new RegistryAuthFailed({ category: "validation", detail });
|
|
22
|
+
/**
|
|
23
|
+
* Read the requested lifetime. Relative forms are exact multiples; an
|
|
24
|
+
* absolute timestamp becomes the distance from now.
|
|
25
|
+
*/
|
|
26
|
+
export const parseExpiresInSeconds = (raw) => {
|
|
27
|
+
const trimmed = raw.trim();
|
|
28
|
+
const relative = /^(\d+)([hdy])$/.exec(trimmed);
|
|
29
|
+
if (relative) {
|
|
30
|
+
const amount = Number(relative[1]);
|
|
31
|
+
const unit = relative[2];
|
|
32
|
+
const multiplier = unit === "h" ? 3_600 : unit === "d" ? 86_400 : 31_536_000;
|
|
33
|
+
return Effect.succeed(amount * multiplier);
|
|
34
|
+
}
|
|
35
|
+
return Option.match(DateTime.make(trimmed), {
|
|
36
|
+
onNone: () => Effect.fail(invalid("Invalid --expires value. Use 7d, 30d, 1y, or an ISO timestamp.")),
|
|
37
|
+
onSome: (expiry) => Effect.map(DateTime.now, (now) => Math.floor(Duration.toSeconds(DateTime.distance(now, expiry)))),
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
/** Enforce the accepted lifetime window. */
|
|
41
|
+
export const validateExpiresInSeconds = (expiresIn) => expiresIn < MIN_TOKEN_LIFETIME_SECONDS || expiresIn > MAX_TOKEN_LIFETIME_SECONDS
|
|
42
|
+
? Effect.fail(invalid("Token expiry must be between 1 hour and 365 days."))
|
|
43
|
+
: Effect.succeed(expiresIn);
|
|
44
|
+
/** Only the authority a caller actually asked for reaches the Registry. */
|
|
45
|
+
export const tokenPermissions = (request) => ({
|
|
46
|
+
...(request.owners.length > 0 ? { owners: request.owners } : {}),
|
|
47
|
+
...(request.extensions.length > 0 ? { extensions: request.extensions } : {}),
|
|
48
|
+
...(Option.isSome(request.permission) ? { permission: request.permission.value } : {}),
|
|
49
|
+
...(Option.isSome(request.orgPermission) ? { org_permission: request.orgPermission.value } : {}),
|
|
50
|
+
...(request.cidr.length > 0 ? { cidr: request.cidr } : {}),
|
|
51
|
+
...(request.bypassMfa ? { bypass_mfa: true } : {}),
|
|
52
|
+
});
|
|
53
|
+
export const createToken = Effect.fn("Tokens.create")(function* (request, registryUrl) {
|
|
54
|
+
const authClient = yield* AuthClient;
|
|
55
|
+
const token = yield* currentToken(registryUrl);
|
|
56
|
+
const expiresIn = yield* parseExpiresInSeconds(request.expires).pipe(Effect.flatMap(validateExpiresInSeconds));
|
|
57
|
+
const created = yield* runWithStepUp((stepUpRequestId) => authClient.createToken(token, { name: request.name, expiresIn, permissions: tokenPermissions(request) }, stepUpRequestId === undefined ? undefined : { stepUpRequestId }), {
|
|
58
|
+
operationLabel: `Create registry token "${request.name}"`,
|
|
59
|
+
waitingLabel: `verification to create registry token "${request.name}"`,
|
|
60
|
+
}, request.verification, registryUrl);
|
|
61
|
+
return { token: created.value, stepUpCompleted: created.stepUpCompleted };
|
|
62
|
+
});
|
|
63
|
+
export const revokeToken = Effect.fn("Tokens.revoke")(function* (tokenId, verification, registryUrl) {
|
|
64
|
+
const authClient = yield* AuthClient;
|
|
65
|
+
const token = yield* currentToken(registryUrl);
|
|
66
|
+
const revoked = yield* runWithStepUp((stepUpRequestId) => authClient.deleteToken(token, tokenId, stepUpRequestId === undefined ? undefined : { stepUpRequestId }), {
|
|
67
|
+
operationLabel: `Revoke registry token ${tokenId}`,
|
|
68
|
+
waitingLabel: `verification to revoke token ${tokenId}`,
|
|
69
|
+
}, verification, registryUrl);
|
|
70
|
+
return { tokenId, stepUpCompleted: revoked.stepUpCompleted };
|
|
71
|
+
});
|
|
72
|
+
export const listTokens = Effect.fn("Tokens.list")(function* (registryUrl) {
|
|
73
|
+
const authClient = yield* AuthClient;
|
|
74
|
+
const presenter = yield* AuthLoginPresenter;
|
|
75
|
+
const token = yield* currentToken(registryUrl);
|
|
76
|
+
return yield* presenter.withProgress({ _tag: "ListingRegistryTokens" }, () => authClient.listTokens(token));
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=tokens.js.map
|
package/package.json
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
"url": "https://github.com/agentxm/axm/issues"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@agentxm/extension-model": "^0.28.
|
|
8
|
-
"@agentxm/registry-client": "^0.28.
|
|
9
|
-
"@agentxm/registry-protocol": "^0.28.
|
|
7
|
+
"@agentxm/extension-model": "^0.28.13",
|
|
8
|
+
"@agentxm/registry-client": "^0.28.13",
|
|
9
|
+
"@agentxm/registry-protocol": "^0.28.13",
|
|
10
10
|
"@napi-rs/keyring": "^1.3.0",
|
|
11
11
|
"effect": "4.0.0-rc.112",
|
|
12
12
|
"proper-lockfile": "^4.1.2"
|
|
13
13
|
},
|
|
14
14
|
"description": "AXM registry-auth feature: login, logout, token, identity inspection, device and loopback flows, and credential lifecycle for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
|
|
15
15
|
"devDependencies": {
|
|
16
|
+
"@agentxm/specification-metadata": "^0.28.13",
|
|
16
17
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
17
18
|
"@effect/vitest": "4.0.0-rc.112",
|
|
18
19
|
"@types/bun": "^1.3.14",
|
|
@@ -55,11 +56,11 @@
|
|
|
55
56
|
"access": "public"
|
|
56
57
|
},
|
|
57
58
|
"repository": {
|
|
58
|
-
"directory": "packages/registry-auth",
|
|
59
|
+
"directory": "packages/supporting/registry-auth",
|
|
59
60
|
"type": "git",
|
|
60
61
|
"url": "https://github.com/agentxm/axm.git"
|
|
61
62
|
},
|
|
62
63
|
"sideEffects": false,
|
|
63
64
|
"type": "module",
|
|
64
|
-
"version": "0.28.
|
|
65
|
-
}
|
|
65
|
+
"version": "0.28.13"
|
|
66
|
+
}
|