@themoltnet/node-red-contrib-core 0.12.3 → 0.12.5
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/nodes/src.js +448 -79
- package/package.json +2 -2
package/dist/nodes/src.js
CHANGED
|
@@ -4,6 +4,59 @@ import crypto, { createHash as createHash$1 } from "crypto";
|
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
|
+
//#region ../sdk/src/errors.ts
|
|
8
|
+
var MoltNetError = class extends Error {
|
|
9
|
+
code;
|
|
10
|
+
statusCode;
|
|
11
|
+
detail;
|
|
12
|
+
/**
|
|
13
|
+
* Populated when the server returned a `VALIDATION_FAILED` problem
|
|
14
|
+
* (status 400) with field-level errors. Empty / undefined for every
|
|
15
|
+
* other problem kind. Proposer scripts surface these to operators so
|
|
16
|
+
* they don't have to re-run with curl to see what was rejected.
|
|
17
|
+
*/
|
|
18
|
+
validationErrors;
|
|
19
|
+
constructor(message, options) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "MoltNetError";
|
|
22
|
+
this.code = options.code;
|
|
23
|
+
this.statusCode = options.statusCode;
|
|
24
|
+
this.detail = options.detail;
|
|
25
|
+
this.validationErrors = options.validationErrors;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var NetworkError = class extends MoltNetError {
|
|
29
|
+
constructor(message, options) {
|
|
30
|
+
super(message, {
|
|
31
|
+
code: "NETWORK_ERROR",
|
|
32
|
+
detail: options?.detail
|
|
33
|
+
});
|
|
34
|
+
this.name = "NetworkError";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var AuthenticationError = class extends MoltNetError {
|
|
38
|
+
constructor(message, options) {
|
|
39
|
+
super(message, {
|
|
40
|
+
code: "AUTH_FAILED",
|
|
41
|
+
statusCode: options?.statusCode,
|
|
42
|
+
detail: options?.detail
|
|
43
|
+
});
|
|
44
|
+
this.name = "AuthenticationError";
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
function problemToError(problem, statusCode) {
|
|
48
|
+
const title = problem.title ?? "Request failed";
|
|
49
|
+
const message = problem.detail ? `${title}: ${problem.detail}` : title;
|
|
50
|
+
const rawErrors = problem.errors;
|
|
51
|
+
const validationErrors = Array.isArray(rawErrors) ? rawErrors.filter((e) => typeof e === "object" && e !== null && typeof e.field === "string" && typeof e.message === "string") : void 0;
|
|
52
|
+
return new MoltNetError(message, {
|
|
53
|
+
code: problem.type ?? problem.code ?? "UNKNOWN",
|
|
54
|
+
statusCode,
|
|
55
|
+
detail: problem.detail,
|
|
56
|
+
validationErrors
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
7
60
|
//#region ../api-client/src/generated/core/bodySerializer.gen.ts
|
|
8
61
|
var jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
|
|
9
62
|
Object.entries({
|
|
@@ -716,7 +769,7 @@ var rotateAgentKey = (options) => (options.client ?? client).post({
|
|
|
716
769
|
...options
|
|
717
770
|
});
|
|
718
771
|
/**
|
|
719
|
-
* Get the authenticated
|
|
772
|
+
* Get the authenticated caller identity and context. Works for both agents (identity plus, under agent-key auth, the credential binding) and humans, via bearer, session, or cookie auth.
|
|
720
773
|
*/
|
|
721
774
|
var getWhoami = (options) => (options?.client ?? client).get({
|
|
722
775
|
security: [
|
|
@@ -799,6 +852,145 @@ var getCryptoIdentity = (options) => (options?.client ?? client).get({
|
|
|
799
852
|
url: "/crypto/identity",
|
|
800
853
|
...options
|
|
801
854
|
});
|
|
855
|
+
var listSigningCredentials = (options) => (options.client ?? client).get({
|
|
856
|
+
security: [
|
|
857
|
+
{
|
|
858
|
+
scheme: "bearer",
|
|
859
|
+
type: "http"
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
name: "X-Moltnet-Session-Token",
|
|
863
|
+
type: "apiKey"
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
in: "cookie",
|
|
867
|
+
name: "ory_kratos_session",
|
|
868
|
+
type: "apiKey"
|
|
869
|
+
}
|
|
870
|
+
],
|
|
871
|
+
url: "/crypto/signing-credentials",
|
|
872
|
+
...options
|
|
873
|
+
});
|
|
874
|
+
var beginSigningCredentialRegistration = (options) => (options.client ?? client).post({
|
|
875
|
+
security: [{
|
|
876
|
+
name: "X-Moltnet-Session-Token",
|
|
877
|
+
type: "apiKey"
|
|
878
|
+
}, {
|
|
879
|
+
in: "cookie",
|
|
880
|
+
name: "ory_kratos_session",
|
|
881
|
+
type: "apiKey"
|
|
882
|
+
}],
|
|
883
|
+
url: "/crypto/signing-credentials/registrations",
|
|
884
|
+
...options,
|
|
885
|
+
headers: {
|
|
886
|
+
"Content-Type": "application/json",
|
|
887
|
+
...options.headers
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
var completeSigningCredentialRegistration = (options) => (options.client ?? client).post({
|
|
891
|
+
security: [{
|
|
892
|
+
name: "X-Moltnet-Session-Token",
|
|
893
|
+
type: "apiKey"
|
|
894
|
+
}, {
|
|
895
|
+
in: "cookie",
|
|
896
|
+
name: "ory_kratos_session",
|
|
897
|
+
type: "apiKey"
|
|
898
|
+
}],
|
|
899
|
+
url: "/crypto/signing-credentials/registrations/{id}/complete",
|
|
900
|
+
...options,
|
|
901
|
+
headers: {
|
|
902
|
+
"Content-Type": "application/json",
|
|
903
|
+
...options.headers
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
var getSigningCredential = (options) => (options.client ?? client).get({
|
|
907
|
+
security: [
|
|
908
|
+
{
|
|
909
|
+
scheme: "bearer",
|
|
910
|
+
type: "http"
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
name: "X-Moltnet-Session-Token",
|
|
914
|
+
type: "apiKey"
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
in: "cookie",
|
|
918
|
+
name: "ory_kratos_session",
|
|
919
|
+
type: "apiKey"
|
|
920
|
+
}
|
|
921
|
+
],
|
|
922
|
+
url: "/crypto/signing-credentials/{id}",
|
|
923
|
+
...options
|
|
924
|
+
});
|
|
925
|
+
var approveSigningCredential = (options) => (options.client ?? client).post({
|
|
926
|
+
security: [
|
|
927
|
+
{
|
|
928
|
+
scheme: "bearer",
|
|
929
|
+
type: "http"
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
name: "X-Moltnet-Session-Token",
|
|
933
|
+
type: "apiKey"
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
in: "cookie",
|
|
937
|
+
name: "ory_kratos_session",
|
|
938
|
+
type: "apiKey"
|
|
939
|
+
}
|
|
940
|
+
],
|
|
941
|
+
url: "/crypto/signing-credentials/{id}/approve",
|
|
942
|
+
...options,
|
|
943
|
+
headers: {
|
|
944
|
+
"Content-Type": "application/json",
|
|
945
|
+
...options.headers
|
|
946
|
+
}
|
|
947
|
+
});
|
|
948
|
+
var revokeSigningCredential = (options) => (options.client ?? client).post({
|
|
949
|
+
security: [
|
|
950
|
+
{
|
|
951
|
+
scheme: "bearer",
|
|
952
|
+
type: "http"
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
name: "X-Moltnet-Session-Token",
|
|
956
|
+
type: "apiKey"
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
in: "cookie",
|
|
960
|
+
name: "ory_kratos_session",
|
|
961
|
+
type: "apiKey"
|
|
962
|
+
}
|
|
963
|
+
],
|
|
964
|
+
url: "/crypto/signing-credentials/{id}/revoke",
|
|
965
|
+
...options,
|
|
966
|
+
headers: {
|
|
967
|
+
"Content-Type": "application/json",
|
|
968
|
+
...options.headers
|
|
969
|
+
}
|
|
970
|
+
});
|
|
971
|
+
var suspendSigningCredential = (options) => (options.client ?? client).post({
|
|
972
|
+
security: [
|
|
973
|
+
{
|
|
974
|
+
scheme: "bearer",
|
|
975
|
+
type: "http"
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
name: "X-Moltnet-Session-Token",
|
|
979
|
+
type: "apiKey"
|
|
980
|
+
},
|
|
981
|
+
{
|
|
982
|
+
in: "cookie",
|
|
983
|
+
name: "ory_kratos_session",
|
|
984
|
+
type: "apiKey"
|
|
985
|
+
}
|
|
986
|
+
],
|
|
987
|
+
url: "/crypto/signing-credentials/{id}/suspend",
|
|
988
|
+
...options,
|
|
989
|
+
headers: {
|
|
990
|
+
"Content-Type": "application/json",
|
|
991
|
+
...options.headers
|
|
992
|
+
}
|
|
993
|
+
});
|
|
802
994
|
/**
|
|
803
995
|
* List signing requests for the authenticated agent.
|
|
804
996
|
*/
|
|
@@ -869,6 +1061,54 @@ var getSigningRequest = (options) => (options.client ?? client).get({
|
|
|
869
1061
|
url: "/crypto/signing-requests/{id}",
|
|
870
1062
|
...options
|
|
871
1063
|
});
|
|
1064
|
+
var claimSigningRequest = (options) => (options.client ?? client).post({
|
|
1065
|
+
security: [{
|
|
1066
|
+
name: "X-Moltnet-Session-Token",
|
|
1067
|
+
type: "apiKey"
|
|
1068
|
+
}, {
|
|
1069
|
+
in: "cookie",
|
|
1070
|
+
name: "ory_kratos_session",
|
|
1071
|
+
type: "apiKey"
|
|
1072
|
+
}],
|
|
1073
|
+
url: "/crypto/signing-requests/{id}/claim",
|
|
1074
|
+
...options,
|
|
1075
|
+
headers: {
|
|
1076
|
+
"Content-Type": "application/json",
|
|
1077
|
+
...options.headers
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
var completeSigningRequest = (options) => (options.client ?? client).post({
|
|
1081
|
+
security: [{
|
|
1082
|
+
name: "X-Moltnet-Session-Token",
|
|
1083
|
+
type: "apiKey"
|
|
1084
|
+
}, {
|
|
1085
|
+
in: "cookie",
|
|
1086
|
+
name: "ory_kratos_session",
|
|
1087
|
+
type: "apiKey"
|
|
1088
|
+
}],
|
|
1089
|
+
url: "/crypto/signing-requests/{id}/complete",
|
|
1090
|
+
...options,
|
|
1091
|
+
headers: {
|
|
1092
|
+
"Content-Type": "application/json",
|
|
1093
|
+
...options.headers
|
|
1094
|
+
}
|
|
1095
|
+
});
|
|
1096
|
+
var rejectSigningRequest = (options) => (options.client ?? client).post({
|
|
1097
|
+
security: [{
|
|
1098
|
+
name: "X-Moltnet-Session-Token",
|
|
1099
|
+
type: "apiKey"
|
|
1100
|
+
}, {
|
|
1101
|
+
in: "cookie",
|
|
1102
|
+
name: "ory_kratos_session",
|
|
1103
|
+
type: "apiKey"
|
|
1104
|
+
}],
|
|
1105
|
+
url: "/crypto/signing-requests/{id}/reject",
|
|
1106
|
+
...options,
|
|
1107
|
+
headers: {
|
|
1108
|
+
"Content-Type": "application/json",
|
|
1109
|
+
...options.headers
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
872
1112
|
/**
|
|
873
1113
|
* Submit a signature for a signing request. The DBOS workflow verifies the signature and updates the request status.
|
|
874
1114
|
*/
|
|
@@ -2896,63 +3136,11 @@ function createRateLimitFetch(options) {
|
|
|
2896
3136
|
});
|
|
2897
3137
|
}
|
|
2898
3138
|
//#endregion
|
|
2899
|
-
//#region ../sdk/src/errors.ts
|
|
2900
|
-
var MoltNetError = class extends Error {
|
|
2901
|
-
code;
|
|
2902
|
-
statusCode;
|
|
2903
|
-
detail;
|
|
2904
|
-
/**
|
|
2905
|
-
* Populated when the server returned a `VALIDATION_FAILED` problem
|
|
2906
|
-
* (status 400) with field-level errors. Empty / undefined for every
|
|
2907
|
-
* other problem kind. Proposer scripts surface these to operators so
|
|
2908
|
-
* they don't have to re-run with curl to see what was rejected.
|
|
2909
|
-
*/
|
|
2910
|
-
validationErrors;
|
|
2911
|
-
constructor(message, options) {
|
|
2912
|
-
super(message);
|
|
2913
|
-
this.name = "MoltNetError";
|
|
2914
|
-
this.code = options.code;
|
|
2915
|
-
this.statusCode = options.statusCode;
|
|
2916
|
-
this.detail = options.detail;
|
|
2917
|
-
this.validationErrors = options.validationErrors;
|
|
2918
|
-
}
|
|
2919
|
-
};
|
|
2920
|
-
var NetworkError = class extends MoltNetError {
|
|
2921
|
-
constructor(message, options) {
|
|
2922
|
-
super(message, {
|
|
2923
|
-
code: "NETWORK_ERROR",
|
|
2924
|
-
detail: options?.detail
|
|
2925
|
-
});
|
|
2926
|
-
this.name = "NetworkError";
|
|
2927
|
-
}
|
|
2928
|
-
};
|
|
2929
|
-
var AuthenticationError = class extends MoltNetError {
|
|
2930
|
-
constructor(message, options) {
|
|
2931
|
-
super(message, {
|
|
2932
|
-
code: "AUTH_FAILED",
|
|
2933
|
-
statusCode: options?.statusCode,
|
|
2934
|
-
detail: options?.detail
|
|
2935
|
-
});
|
|
2936
|
-
this.name = "AuthenticationError";
|
|
2937
|
-
}
|
|
2938
|
-
};
|
|
2939
|
-
function problemToError(problem, statusCode) {
|
|
2940
|
-
const title = problem.title ?? "Request failed";
|
|
2941
|
-
const message = problem.detail ? `${title}: ${problem.detail}` : title;
|
|
2942
|
-
const rawErrors = problem.errors;
|
|
2943
|
-
const validationErrors = Array.isArray(rawErrors) ? rawErrors.filter((e) => typeof e === "object" && e !== null && typeof e.field === "string" && typeof e.message === "string") : void 0;
|
|
2944
|
-
return new MoltNetError(message, {
|
|
2945
|
-
code: problem.type ?? problem.code ?? "UNKNOWN",
|
|
2946
|
-
statusCode,
|
|
2947
|
-
detail: problem.detail,
|
|
2948
|
-
validationErrors
|
|
2949
|
-
});
|
|
2950
|
-
}
|
|
2951
|
-
//#endregion
|
|
2952
3139
|
//#region ../sdk/src/agent-context.ts
|
|
2953
3140
|
function unwrapResult(result) {
|
|
2954
3141
|
if (result.error !== void 0 && result.error !== null) {
|
|
2955
3142
|
const error = result.error;
|
|
3143
|
+
if (error instanceof MoltNetError) throw error;
|
|
2956
3144
|
if (isProblemDetails(error)) throw problemToError(error, error.status);
|
|
2957
3145
|
if (error instanceof Error && result.response === void 0) {
|
|
2958
3146
|
const networkError = new NetworkError(error.message, { detail: error.cause ? stringifyUnknown(error.cause) : void 0 });
|
|
@@ -3075,16 +3263,25 @@ function createAgentKeysNamespace(context) {
|
|
|
3075
3263
|
};
|
|
3076
3264
|
}
|
|
3077
3265
|
//#endregion
|
|
3266
|
+
//#region ../sdk/src/namespaces/whoami.ts
|
|
3267
|
+
/**
|
|
3268
|
+
* Build a `whoami()` accessor bound to an authenticated context. Returns the
|
|
3269
|
+
* caller's identity and context: `subjectType`, `currentTeamId`, and, for an
|
|
3270
|
+
* agent authenticated via an agent key, its `credentialBinding`.
|
|
3271
|
+
*/
|
|
3272
|
+
function createWhoami(context) {
|
|
3273
|
+
const { client, auth } = context;
|
|
3274
|
+
return async () => unwrapResult(await getWhoami({
|
|
3275
|
+
client,
|
|
3276
|
+
auth
|
|
3277
|
+
}));
|
|
3278
|
+
}
|
|
3279
|
+
//#endregion
|
|
3078
3280
|
//#region ../sdk/src/namespaces/agents.ts
|
|
3079
3281
|
function createAgentsNamespace(context) {
|
|
3080
|
-
const { client
|
|
3282
|
+
const { client } = context;
|
|
3081
3283
|
return {
|
|
3082
|
-
|
|
3083
|
-
return unwrapResult(await getWhoami({
|
|
3084
|
-
client,
|
|
3085
|
-
auth
|
|
3086
|
-
}));
|
|
3087
|
-
},
|
|
3284
|
+
whoami: createWhoami(context),
|
|
3088
3285
|
async lookup(fingerprint) {
|
|
3089
3286
|
return unwrapResult(await getAgentProfile({
|
|
3090
3287
|
client,
|
|
@@ -3113,7 +3310,7 @@ function createAuthNamespace(context) {
|
|
|
3113
3310
|
}
|
|
3114
3311
|
//#endregion
|
|
3115
3312
|
//#region ../sdk/src/namespaces/crypto.ts
|
|
3116
|
-
function createCryptoNamespace(context, signingRequests) {
|
|
3313
|
+
function createCryptoNamespace(context, signingRequests, signingCredentials) {
|
|
3117
3314
|
const { client, auth } = context;
|
|
3118
3315
|
return {
|
|
3119
3316
|
async identity() {
|
|
@@ -3128,7 +3325,8 @@ function createCryptoNamespace(context, signingRequests) {
|
|
|
3128
3325
|
body
|
|
3129
3326
|
}));
|
|
3130
3327
|
},
|
|
3131
|
-
signingRequests
|
|
3328
|
+
signingRequests,
|
|
3329
|
+
signingCredentials
|
|
3132
3330
|
};
|
|
3133
3331
|
}
|
|
3134
3332
|
//#endregion
|
|
@@ -5420,6 +5618,70 @@ function createRuntimeSlotsNamespace(context) {
|
|
|
5420
5618
|
};
|
|
5421
5619
|
}
|
|
5422
5620
|
//#endregion
|
|
5621
|
+
//#region ../sdk/src/namespaces/signing-credentials.ts
|
|
5622
|
+
function createSigningCredentialsNamespace(context) {
|
|
5623
|
+
const { client, auth } = context;
|
|
5624
|
+
return {
|
|
5625
|
+
async list(query, options) {
|
|
5626
|
+
return unwrapResult(await listSigningCredentials({
|
|
5627
|
+
client,
|
|
5628
|
+
auth,
|
|
5629
|
+
headers: requiredTeamHeaders(options),
|
|
5630
|
+
query
|
|
5631
|
+
}));
|
|
5632
|
+
},
|
|
5633
|
+
async get(id, options) {
|
|
5634
|
+
return unwrapResult(await getSigningCredential({
|
|
5635
|
+
client,
|
|
5636
|
+
auth,
|
|
5637
|
+
headers: requiredTeamHeaders(options),
|
|
5638
|
+
path: { id }
|
|
5639
|
+
}));
|
|
5640
|
+
},
|
|
5641
|
+
async startRegistration(body, options) {
|
|
5642
|
+
return unwrapResult(await beginSigningCredentialRegistration({
|
|
5643
|
+
client,
|
|
5644
|
+
auth,
|
|
5645
|
+
headers: requiredTeamHeaders(options),
|
|
5646
|
+
body
|
|
5647
|
+
}));
|
|
5648
|
+
},
|
|
5649
|
+
async completeRegistration(id, body, options) {
|
|
5650
|
+
return unwrapResult(await completeSigningCredentialRegistration({
|
|
5651
|
+
client,
|
|
5652
|
+
auth,
|
|
5653
|
+
headers: requiredTeamHeaders(options),
|
|
5654
|
+
path: { id },
|
|
5655
|
+
body
|
|
5656
|
+
}));
|
|
5657
|
+
},
|
|
5658
|
+
async approve(id, options) {
|
|
5659
|
+
return unwrapResult(await approveSigningCredential({
|
|
5660
|
+
client,
|
|
5661
|
+
auth,
|
|
5662
|
+
headers: requiredTeamHeaders(options),
|
|
5663
|
+
path: { id }
|
|
5664
|
+
}));
|
|
5665
|
+
},
|
|
5666
|
+
async suspend(id, options) {
|
|
5667
|
+
return unwrapResult(await suspendSigningCredential({
|
|
5668
|
+
client,
|
|
5669
|
+
auth,
|
|
5670
|
+
headers: requiredTeamHeaders(options),
|
|
5671
|
+
path: { id }
|
|
5672
|
+
}));
|
|
5673
|
+
},
|
|
5674
|
+
async revoke(id, options) {
|
|
5675
|
+
return unwrapResult(await revokeSigningCredential({
|
|
5676
|
+
client,
|
|
5677
|
+
auth,
|
|
5678
|
+
headers: requiredTeamHeaders(options),
|
|
5679
|
+
path: { id }
|
|
5680
|
+
}));
|
|
5681
|
+
}
|
|
5682
|
+
};
|
|
5683
|
+
}
|
|
5684
|
+
//#endregion
|
|
5423
5685
|
//#region ../sdk/src/namespaces/signing-requests.ts
|
|
5424
5686
|
function createSigningRequestsNamespace(context) {
|
|
5425
5687
|
const { client, auth } = context;
|
|
@@ -5452,6 +5714,33 @@ function createSigningRequestsNamespace(context) {
|
|
|
5452
5714
|
path: { id },
|
|
5453
5715
|
body
|
|
5454
5716
|
}));
|
|
5717
|
+
},
|
|
5718
|
+
async claim(id, body, options) {
|
|
5719
|
+
return unwrapResult(await claimSigningRequest({
|
|
5720
|
+
client,
|
|
5721
|
+
auth,
|
|
5722
|
+
headers: requiredTeamHeaders(options),
|
|
5723
|
+
path: { id },
|
|
5724
|
+
body
|
|
5725
|
+
}));
|
|
5726
|
+
},
|
|
5727
|
+
async complete(id, body, options) {
|
|
5728
|
+
return unwrapResult(await completeSigningRequest({
|
|
5729
|
+
client,
|
|
5730
|
+
auth,
|
|
5731
|
+
headers: requiredTeamHeaders(options),
|
|
5732
|
+
path: { id },
|
|
5733
|
+
body
|
|
5734
|
+
}));
|
|
5735
|
+
},
|
|
5736
|
+
async reject(id, body, options) {
|
|
5737
|
+
return unwrapResult(await rejectSigningRequest({
|
|
5738
|
+
client,
|
|
5739
|
+
auth,
|
|
5740
|
+
headers: requiredTeamHeaders(options),
|
|
5741
|
+
path: { id },
|
|
5742
|
+
body
|
|
5743
|
+
}));
|
|
5455
5744
|
}
|
|
5456
5745
|
};
|
|
5457
5746
|
}
|
|
@@ -15664,7 +15953,7 @@ function createAgent(options) {
|
|
|
15664
15953
|
packs: createPacksNamespace(context),
|
|
15665
15954
|
entries: createEntriesNamespace(context),
|
|
15666
15955
|
agents: createAgentsNamespace(context),
|
|
15667
|
-
crypto: createCryptoNamespace(context, createSigningRequestsNamespace(context)),
|
|
15956
|
+
crypto: createCryptoNamespace(context, createSigningRequestsNamespace(context), createSigningCredentialsNamespace(context)),
|
|
15668
15957
|
vouch: createVouchNamespace(context),
|
|
15669
15958
|
auth: createAuthNamespace(context),
|
|
15670
15959
|
recovery: createRecoveryNamespace(context),
|
|
@@ -15677,22 +15966,37 @@ function createAgent(options) {
|
|
|
15677
15966
|
runtimeSlots: createRuntimeSlotsNamespace(context),
|
|
15678
15967
|
runtimeSessions: createRuntimeSessionsNamespace(context),
|
|
15679
15968
|
client,
|
|
15680
|
-
getToken: () =>
|
|
15969
|
+
getToken: () => {
|
|
15970
|
+
if (tokenManager) return tokenManager.getToken();
|
|
15971
|
+
if (auth) return auth();
|
|
15972
|
+
return Promise.reject(new MoltNetError("No token source configured", { code: "NO_TOKEN_SOURCE" }));
|
|
15973
|
+
}
|
|
15681
15974
|
};
|
|
15682
15975
|
}
|
|
15683
15976
|
//#endregion
|
|
15684
15977
|
//#region ../sdk/src/config.ts
|
|
15685
15978
|
/**
|
|
15686
15979
|
* Read MoltNet credentials from environment variables.
|
|
15687
|
-
* Reads MOLTNET_CLIENT_ID, MOLTNET_CLIENT_SECRET, and
|
|
15980
|
+
* Reads MOLTNET_CLIENT_ID, MOLTNET_CLIENT_SECRET, MOLTNET_API_URL, and
|
|
15981
|
+
* MOLTNET_AGENT_KEY.
|
|
15688
15982
|
*/
|
|
15689
15983
|
function readEnvCredentials() {
|
|
15690
15984
|
return {
|
|
15691
15985
|
clientId: process.env.MOLTNET_CLIENT_ID,
|
|
15692
15986
|
clientSecret: process.env.MOLTNET_CLIENT_SECRET,
|
|
15693
|
-
apiUrl: process.env.MOLTNET_API_URL
|
|
15987
|
+
apiUrl: process.env.MOLTNET_API_URL,
|
|
15988
|
+
agentKey: process.env.MOLTNET_AGENT_KEY
|
|
15694
15989
|
};
|
|
15695
15990
|
}
|
|
15991
|
+
/**
|
|
15992
|
+
* Resolve the API base URL from an ordered list of candidates, falling back to
|
|
15993
|
+
* the hosted default, with any trailing slash stripped. Candidates are tried in
|
|
15994
|
+
* order — pass them highest-precedence first (typically explicit option, then
|
|
15995
|
+
* env, then config file) so every caller shares one precedence rule.
|
|
15996
|
+
*/
|
|
15997
|
+
function normalizeApiUrl(...candidates) {
|
|
15998
|
+
return (candidates.find((c) => c) ?? "https://api.themolt.net").replace(/\/$/, "");
|
|
15999
|
+
}
|
|
15696
16000
|
//#endregion
|
|
15697
16001
|
//#region ../sdk/src/credentials.ts
|
|
15698
16002
|
function getConfigDir() {
|
|
@@ -15756,6 +16060,32 @@ function createRetryFetch(tokenManager, options) {
|
|
|
15756
16060
|
return doFetch(init);
|
|
15757
16061
|
};
|
|
15758
16062
|
}
|
|
16063
|
+
/**
|
|
16064
|
+
* Create a fetch wrapper for agent-key (static-bearer) authentication.
|
|
16065
|
+
*
|
|
16066
|
+
* A static key cannot be refreshed, so there is no token-invalidation/replay
|
|
16067
|
+
* (that half of {@link createRetryFetch} is intentionally omitted). What remains
|
|
16068
|
+
* is orthogonal to token refresh and still matters for a long-running client:
|
|
16069
|
+
*
|
|
16070
|
+
* - **429**: delegates to `createRateLimitFetch` (Retry-After / backoff), unless
|
|
16071
|
+
* `retry` is `false`.
|
|
16072
|
+
* - **401**: the key was rejected (revoked, expired, or not authorized for the
|
|
16073
|
+
* requested team). Rather than silently returning a bare 401 on every call,
|
|
16074
|
+
* throw an actionable {@link AuthenticationError}. The key value is never
|
|
16075
|
+
* included in the message.
|
|
16076
|
+
*/
|
|
16077
|
+
function createAgentKeyFetch(retry) {
|
|
16078
|
+
const rateLimitFetch = retry === false ? fetch : createRateLimitFetch({
|
|
16079
|
+
maxRetries: retry?.maxRateLimitRetries,
|
|
16080
|
+
baseDelayMs: retry?.baseDelayMs,
|
|
16081
|
+
maxDelayMs: retry?.maxDelayMs
|
|
16082
|
+
});
|
|
16083
|
+
return async (input, init) => {
|
|
16084
|
+
const response = await rateLimitFetch(input, init);
|
|
16085
|
+
if (response.status === 401) throw new AuthenticationError("agent key rejected (401): the key is revoked, expired, or not authorized for the requested team — re-provision the key.", { statusCode: 401 });
|
|
16086
|
+
return response;
|
|
16087
|
+
};
|
|
16088
|
+
}
|
|
15759
16089
|
//#endregion
|
|
15760
16090
|
//#region ../sdk/src/token.ts
|
|
15761
16091
|
var TokenManager = class {
|
|
@@ -15815,37 +16145,76 @@ var TokenManager = class {
|
|
|
15815
16145
|
};
|
|
15816
16146
|
//#endregion
|
|
15817
16147
|
//#region ../sdk/src/connect.ts
|
|
15818
|
-
|
|
15819
|
-
|
|
16148
|
+
async function resolveConnection(options) {
|
|
16149
|
+
const env = readEnvCredentials();
|
|
16150
|
+
const explicitAgentKey = options.agentKey?.trim();
|
|
16151
|
+
if (explicitAgentKey) {
|
|
16152
|
+
const config = await readConfig(options.configDir);
|
|
16153
|
+
return {
|
|
16154
|
+
mode: "agentKey",
|
|
16155
|
+
agentKey: explicitAgentKey,
|
|
16156
|
+
apiUrl: normalizeApiUrl(options.apiUrl, env.apiUrl, config?.endpoints?.api)
|
|
16157
|
+
};
|
|
16158
|
+
}
|
|
15820
16159
|
if (options.clientId && options.clientSecret) return {
|
|
16160
|
+
mode: "oauth2",
|
|
15821
16161
|
clientId: options.clientId,
|
|
15822
16162
|
clientSecret: options.clientSecret,
|
|
15823
|
-
apiUrl: (options.apiUrl
|
|
16163
|
+
apiUrl: normalizeApiUrl(options.apiUrl, env.apiUrl)
|
|
15824
16164
|
};
|
|
15825
|
-
const
|
|
16165
|
+
const envAgentKey = env.agentKey?.trim();
|
|
16166
|
+
if (envAgentKey) {
|
|
16167
|
+
const config = await readConfig(options.configDir);
|
|
16168
|
+
return {
|
|
16169
|
+
mode: "agentKey",
|
|
16170
|
+
agentKey: envAgentKey,
|
|
16171
|
+
apiUrl: normalizeApiUrl(options.apiUrl, env.apiUrl, config?.endpoints?.api)
|
|
16172
|
+
};
|
|
16173
|
+
}
|
|
15826
16174
|
if (env.clientId && env.clientSecret) return {
|
|
16175
|
+
mode: "oauth2",
|
|
15827
16176
|
clientId: env.clientId,
|
|
15828
16177
|
clientSecret: env.clientSecret,
|
|
15829
|
-
apiUrl: (
|
|
16178
|
+
apiUrl: normalizeApiUrl(options.apiUrl, env.apiUrl)
|
|
15830
16179
|
};
|
|
15831
16180
|
const config = await readConfig(options.configDir);
|
|
15832
16181
|
if (config?.oauth2?.client_id && config?.oauth2?.client_secret) return {
|
|
16182
|
+
mode: "oauth2",
|
|
15833
16183
|
clientId: config.oauth2.client_id,
|
|
15834
16184
|
clientSecret: config.oauth2.client_secret,
|
|
15835
|
-
apiUrl: (options.apiUrl
|
|
16185
|
+
apiUrl: normalizeApiUrl(options.apiUrl, config.endpoints?.api)
|
|
15836
16186
|
};
|
|
15837
|
-
throw new MoltNetError("No credentials found. Provide clientId/clientSecret, set MOLTNET_CLIENT_ID/MOLTNET_CLIENT_SECRET
|
|
16187
|
+
throw new MoltNetError("No credentials found. Provide an agentKey / MOLTNET_AGENT_KEY, clientId/clientSecret, set MOLTNET_CLIENT_ID/MOLTNET_CLIENT_SECRET, or run `moltnet register` first.", { code: "NO_CREDENTIALS" });
|
|
15838
16188
|
}
|
|
15839
16189
|
/**
|
|
15840
16190
|
* Connect to MoltNet and return an authenticated Agent facade.
|
|
15841
16191
|
*
|
|
15842
|
-
* Credential resolution
|
|
15843
|
-
*
|
|
15844
|
-
*
|
|
15845
|
-
*
|
|
16192
|
+
* Credential resolution, highest precedence first. Explicit in-code options —
|
|
16193
|
+
* of either kind — always win over the environment and config file:
|
|
16194
|
+
* 1. Explicit `agentKey` option → agent-key mode (static bearer)
|
|
16195
|
+
* 2. Explicit `clientId` / `clientSecret` → OAuth2 client-credentials
|
|
16196
|
+
* 3. `MOLTNET_AGENT_KEY` env → agent-key mode
|
|
16197
|
+
* 4. `MOLTNET_CLIENT_ID` / `MOLTNET_CLIENT_SECRET` env → OAuth2
|
|
16198
|
+
* 5. Config file (`~/.config/moltnet/moltnet.json`) → OAuth2
|
|
16199
|
+
*
|
|
16200
|
+
* In agent-key mode the key is sent directly as a bearer token — no OAuth2
|
|
16201
|
+
* round-trip — and 429 backoff still applies; a rejected key surfaces an
|
|
16202
|
+
* `AuthenticationError`.
|
|
15846
16203
|
*/
|
|
15847
16204
|
async function connect(options = {}) {
|
|
15848
|
-
const
|
|
16205
|
+
const resolved = await resolveConnection(options);
|
|
16206
|
+
if (resolved.mode === "agentKey") {
|
|
16207
|
+
const client = createClient({
|
|
16208
|
+
baseUrl: resolved.apiUrl,
|
|
16209
|
+
fetch: createAgentKeyFetch(options.retry)
|
|
16210
|
+
});
|
|
16211
|
+
const auth = () => Promise.resolve(resolved.agentKey);
|
|
16212
|
+
return createAgent({
|
|
16213
|
+
client,
|
|
16214
|
+
auth
|
|
16215
|
+
});
|
|
16216
|
+
}
|
|
16217
|
+
const creds = resolved;
|
|
15849
16218
|
const autoToken = options.autoToken ?? true;
|
|
15850
16219
|
const tokenManager = new TokenManager({
|
|
15851
16220
|
clientId: creds.clientId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themoltnet/node-red-contrib-core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Node-RED nodes for the MoltNet API",
|
|
6
6
|
"keywords": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"main": "dist/nodes/agent.js",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@themoltnet/sdk": "0.
|
|
49
|
+
"@themoltnet/sdk": "0.125.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/node": "^22.19.0",
|