chainlesschain 0.81.0 → 0.132.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/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/commands/agent-network.js +254 -1
- package/src/commands/audit.js +302 -0
- package/src/commands/automation.js +271 -1
- package/src/commands/codegen.js +224 -0
- package/src/commands/collab.js +341 -0
- package/src/commands/compliance.js +1035 -0
- package/src/commands/cowork.js +221 -0
- package/src/commands/dbevo.js +284 -0
- package/src/commands/dev.js +252 -0
- package/src/commands/did.js +358 -0
- package/src/commands/encrypt.js +341 -0
- package/src/commands/export.js +256 -1
- package/src/commands/fusion.js +258 -0
- package/src/commands/governance.js +325 -0
- package/src/commands/hardening.js +411 -0
- package/src/commands/hook.js +148 -0
- package/src/commands/import.js +252 -0
- package/src/commands/incentive.js +322 -0
- package/src/commands/infra.js +244 -0
- package/src/commands/instinct.js +260 -0
- package/src/commands/ipfs.js +318 -0
- package/src/commands/kg.js +387 -0
- package/src/commands/llm.js +263 -0
- package/src/commands/mcp.js +221 -0
- package/src/commands/memory.js +248 -0
- package/src/commands/multimodal.js +296 -0
- package/src/commands/nlprog.js +356 -0
- package/src/commands/note.js +244 -0
- package/src/commands/ops.js +354 -0
- package/src/commands/orchestrate.js +166 -0
- package/src/commands/org.js +277 -0
- package/src/commands/p2p.js +390 -0
- package/src/commands/perception.js +290 -0
- package/src/commands/permmem.js +251 -0
- package/src/commands/plugin-ecosystem.js +273 -0
- package/src/commands/pqc.js +393 -0
- package/src/commands/quantization.js +351 -0
- package/src/commands/rcache.js +271 -0
- package/src/commands/recommend.js +340 -0
- package/src/commands/runtime.js +307 -0
- package/src/commands/scim.js +262 -0
- package/src/commands/session.js +258 -0
- package/src/commands/skill.js +267 -1
- package/src/commands/social.js +256 -0
- package/src/commands/sso.js +186 -1
- package/src/commands/sync.js +256 -0
- package/src/commands/tech.js +338 -0
- package/src/commands/tenant.js +351 -0
- package/src/commands/tokens.js +269 -0
- package/src/commands/trust.js +249 -0
- package/src/commands/wallet.js +277 -0
- package/src/commands/workflow.js +171 -0
- package/src/index.js +4 -0
- package/src/lib/agent-coordinator.js +325 -0
- package/src/lib/agent-network.js +387 -0
- package/src/lib/agent-router.js +395 -0
- package/src/lib/aiops.js +478 -0
- package/src/lib/audit-logger.js +379 -0
- package/src/lib/automation-engine.js +330 -0
- package/src/lib/autonomous-developer.js +350 -0
- package/src/lib/code-agent.js +323 -0
- package/src/lib/collaboration-governance.js +364 -0
- package/src/lib/community-governance.js +436 -0
- package/src/lib/compliance-manager.js +434 -0
- package/src/lib/content-recommendation.js +469 -0
- package/src/lib/crypto-manager.js +350 -0
- package/src/lib/dbevo.js +338 -0
- package/src/lib/decentral-infra.js +340 -0
- package/src/lib/did-manager.js +367 -0
- package/src/lib/hardening-manager.js +348 -0
- package/src/lib/hook-manager.js +380 -0
- package/src/lib/instinct-manager.js +332 -0
- package/src/lib/ipfs-storage.js +334 -0
- package/src/lib/knowledge-exporter.js +381 -0
- package/src/lib/knowledge-graph.js +432 -0
- package/src/lib/knowledge-importer.js +379 -0
- package/src/lib/llm-providers.js +391 -0
- package/src/lib/mcp-registry.js +333 -0
- package/src/lib/memory-manager.js +330 -0
- package/src/lib/multimodal.js +346 -0
- package/src/lib/nl-programming.js +343 -0
- package/src/lib/note-versioning.js +327 -0
- package/src/lib/org-manager.js +323 -0
- package/src/lib/p2p-manager.js +387 -0
- package/src/lib/perception.js +346 -0
- package/src/lib/perf-tuning.js +4 -1
- package/src/lib/permanent-memory.js +320 -0
- package/src/lib/plugin-ecosystem.js +377 -0
- package/src/lib/pqc-manager.js +368 -0
- package/src/lib/protocol-fusion.js +417 -0
- package/src/lib/quantization.js +325 -0
- package/src/lib/response-cache.js +327 -0
- package/src/lib/scim-manager.js +329 -0
- package/src/lib/session-manager.js +329 -0
- package/src/lib/skill-loader.js +377 -0
- package/src/lib/social-manager.js +326 -0
- package/src/lib/sso-manager.js +332 -0
- package/src/lib/sync-manager.js +326 -0
- package/src/lib/tech-learning-engine.js +369 -0
- package/src/lib/tenant-saas.js +460 -0
- package/src/lib/threat-intel.js +335 -0
- package/src/lib/token-incentive.js +293 -0
- package/src/lib/token-tracker.js +329 -0
- package/src/lib/trust-security.js +390 -0
- package/src/lib/ueba.js +389 -0
- package/src/lib/universal-runtime.js +325 -0
- package/src/lib/wallet-manager.js +326 -0
- package/src/lib/workflow-engine.js +322 -0
package/src/lib/sso-manager.js
CHANGED
|
@@ -839,3 +839,335 @@ export function getStats(db) {
|
|
|
839
839
|
},
|
|
840
840
|
};
|
|
841
841
|
}
|
|
842
|
+
|
|
843
|
+
// ===== V2 Surface (cli 0.130.0) — in-memory governance =====
|
|
844
|
+
export const PROVIDER_MATURITY_V2 = Object.freeze({
|
|
845
|
+
PENDING: "pending",
|
|
846
|
+
ACTIVE: "active",
|
|
847
|
+
DEPRECATED: "deprecated",
|
|
848
|
+
RETIRED: "retired",
|
|
849
|
+
});
|
|
850
|
+
export const LOGIN_LIFECYCLE_V2 = Object.freeze({
|
|
851
|
+
QUEUED: "queued",
|
|
852
|
+
AUTHENTICATING: "authenticating",
|
|
853
|
+
AUTHENTICATED: "authenticated",
|
|
854
|
+
FAILED: "failed",
|
|
855
|
+
CANCELLED: "cancelled",
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
const _PM_V2 = PROVIDER_MATURITY_V2;
|
|
859
|
+
const _LL_V2 = LOGIN_LIFECYCLE_V2;
|
|
860
|
+
const _PM_TRANS_V2 = new Map([
|
|
861
|
+
[_PM_V2.PENDING, new Set([_PM_V2.ACTIVE, _PM_V2.RETIRED])],
|
|
862
|
+
[_PM_V2.ACTIVE, new Set([_PM_V2.DEPRECATED, _PM_V2.RETIRED])],
|
|
863
|
+
[_PM_V2.DEPRECATED, new Set([_PM_V2.ACTIVE, _PM_V2.RETIRED])],
|
|
864
|
+
[_PM_V2.RETIRED, new Set()],
|
|
865
|
+
]);
|
|
866
|
+
const _LL_TRANS_V2 = new Map([
|
|
867
|
+
[_LL_V2.QUEUED, new Set([_LL_V2.AUTHENTICATING, _LL_V2.CANCELLED])],
|
|
868
|
+
[
|
|
869
|
+
_LL_V2.AUTHENTICATING,
|
|
870
|
+
new Set([_LL_V2.AUTHENTICATED, _LL_V2.FAILED, _LL_V2.CANCELLED]),
|
|
871
|
+
],
|
|
872
|
+
[_LL_V2.AUTHENTICATED, new Set()],
|
|
873
|
+
[_LL_V2.FAILED, new Set()],
|
|
874
|
+
[_LL_V2.CANCELLED, new Set()],
|
|
875
|
+
]);
|
|
876
|
+
const _LL_TERM_V2 = new Set([
|
|
877
|
+
_LL_V2.AUTHENTICATED,
|
|
878
|
+
_LL_V2.FAILED,
|
|
879
|
+
_LL_V2.CANCELLED,
|
|
880
|
+
]);
|
|
881
|
+
|
|
882
|
+
const SSO_DEFAULT_MAX_ACTIVE_PROVIDERS_PER_OWNER = 8;
|
|
883
|
+
const SSO_DEFAULT_MAX_PENDING_LOGINS_PER_PROVIDER = 16;
|
|
884
|
+
const SSO_DEFAULT_PROVIDER_IDLE_MS = 30 * 24 * 60 * 60 * 1000;
|
|
885
|
+
const SSO_DEFAULT_LOGIN_STUCK_MS = 5 * 60 * 1000;
|
|
886
|
+
|
|
887
|
+
const _ssoProvidersV2 = new Map();
|
|
888
|
+
const _ssoLoginsV2 = new Map();
|
|
889
|
+
let _ssoConfigV2 = {
|
|
890
|
+
maxActiveProvidersPerOwner: SSO_DEFAULT_MAX_ACTIVE_PROVIDERS_PER_OWNER,
|
|
891
|
+
maxPendingLoginsPerProvider: SSO_DEFAULT_MAX_PENDING_LOGINS_PER_PROVIDER,
|
|
892
|
+
providerIdleMs: SSO_DEFAULT_PROVIDER_IDLE_MS,
|
|
893
|
+
loginStuckMs: SSO_DEFAULT_LOGIN_STUCK_MS,
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
function _ssoPosIntV2(n, label) {
|
|
897
|
+
if (typeof n !== "number" || !isFinite(n) || isNaN(n))
|
|
898
|
+
throw new Error(`${label} must be positive integer`);
|
|
899
|
+
const v = Math.floor(n);
|
|
900
|
+
if (v <= 0) throw new Error(`${label} must be positive integer`);
|
|
901
|
+
return v;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
export function _resetStateSsoManagerV2() {
|
|
905
|
+
_ssoProvidersV2.clear();
|
|
906
|
+
_ssoLoginsV2.clear();
|
|
907
|
+
_ssoConfigV2 = {
|
|
908
|
+
maxActiveProvidersPerOwner: SSO_DEFAULT_MAX_ACTIVE_PROVIDERS_PER_OWNER,
|
|
909
|
+
maxPendingLoginsPerProvider: SSO_DEFAULT_MAX_PENDING_LOGINS_PER_PROVIDER,
|
|
910
|
+
providerIdleMs: SSO_DEFAULT_PROVIDER_IDLE_MS,
|
|
911
|
+
loginStuckMs: SSO_DEFAULT_LOGIN_STUCK_MS,
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
export function setMaxActiveProvidersPerOwnerV2(n) {
|
|
916
|
+
_ssoConfigV2.maxActiveProvidersPerOwner = _ssoPosIntV2(
|
|
917
|
+
n,
|
|
918
|
+
"maxActiveProvidersPerOwner",
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
export function setMaxPendingLoginsPerProviderV2(n) {
|
|
922
|
+
_ssoConfigV2.maxPendingLoginsPerProvider = _ssoPosIntV2(
|
|
923
|
+
n,
|
|
924
|
+
"maxPendingLoginsPerProvider",
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
export function setProviderIdleMsV2(n) {
|
|
928
|
+
_ssoConfigV2.providerIdleMs = _ssoPosIntV2(n, "providerIdleMs");
|
|
929
|
+
}
|
|
930
|
+
export function setLoginStuckMsV2(n) {
|
|
931
|
+
_ssoConfigV2.loginStuckMs = _ssoPosIntV2(n, "loginStuckMs");
|
|
932
|
+
}
|
|
933
|
+
export function getMaxActiveProvidersPerOwnerV2() {
|
|
934
|
+
return _ssoConfigV2.maxActiveProvidersPerOwner;
|
|
935
|
+
}
|
|
936
|
+
export function getMaxPendingLoginsPerProviderV2() {
|
|
937
|
+
return _ssoConfigV2.maxPendingLoginsPerProvider;
|
|
938
|
+
}
|
|
939
|
+
export function getProviderIdleMsV2() {
|
|
940
|
+
return _ssoConfigV2.providerIdleMs;
|
|
941
|
+
}
|
|
942
|
+
export function getLoginStuckMsV2() {
|
|
943
|
+
return _ssoConfigV2.loginStuckMs;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
function _copyProviderV2(p) {
|
|
947
|
+
return { ...p, metadata: { ...(p.metadata || {}) } };
|
|
948
|
+
}
|
|
949
|
+
function _copyLoginV2(l) {
|
|
950
|
+
return { ...l, metadata: { ...(l.metadata || {}) } };
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
export function registerProviderV2({
|
|
954
|
+
id,
|
|
955
|
+
owner,
|
|
956
|
+
protocol,
|
|
957
|
+
displayName,
|
|
958
|
+
metadata,
|
|
959
|
+
} = {}) {
|
|
960
|
+
if (!id || typeof id !== "string") throw new Error("id required");
|
|
961
|
+
if (!owner || typeof owner !== "string") throw new Error("owner required");
|
|
962
|
+
if (!protocol || typeof protocol !== "string")
|
|
963
|
+
throw new Error("protocol required");
|
|
964
|
+
if (_ssoProvidersV2.has(id))
|
|
965
|
+
throw new Error(`provider ${id} already registered`);
|
|
966
|
+
const now = Date.now();
|
|
967
|
+
const p = {
|
|
968
|
+
id,
|
|
969
|
+
owner,
|
|
970
|
+
protocol,
|
|
971
|
+
displayName: displayName || id,
|
|
972
|
+
status: _PM_V2.PENDING,
|
|
973
|
+
activatedAt: null,
|
|
974
|
+
retiredAt: null,
|
|
975
|
+
lastSeenAt: now,
|
|
976
|
+
createdAt: now,
|
|
977
|
+
metadata: metadata && typeof metadata === "object" ? { ...metadata } : {},
|
|
978
|
+
};
|
|
979
|
+
_ssoProvidersV2.set(id, p);
|
|
980
|
+
return _copyProviderV2(p);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function _activeProviderCountForOwnerV2(owner) {
|
|
984
|
+
let c = 0;
|
|
985
|
+
for (const p of _ssoProvidersV2.values())
|
|
986
|
+
if (p.owner === owner && p.status === _PM_V2.ACTIVE) c++;
|
|
987
|
+
return c;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
function _transitionProviderV2(id, next) {
|
|
991
|
+
const p = _ssoProvidersV2.get(id);
|
|
992
|
+
if (!p) throw new Error(`provider ${id} not found`);
|
|
993
|
+
const allowed = _PM_TRANS_V2.get(p.status);
|
|
994
|
+
if (!allowed || !allowed.has(next))
|
|
995
|
+
throw new Error(`invalid transition ${p.status} -> ${next}`);
|
|
996
|
+
if (next === _PM_V2.ACTIVE && p.status === _PM_V2.PENDING) {
|
|
997
|
+
if (
|
|
998
|
+
_activeProviderCountForOwnerV2(p.owner) >=
|
|
999
|
+
_ssoConfigV2.maxActiveProvidersPerOwner
|
|
1000
|
+
) {
|
|
1001
|
+
throw new Error(
|
|
1002
|
+
`owner ${p.owner} active-provider cap reached (${_ssoConfigV2.maxActiveProvidersPerOwner})`,
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
const now = Date.now();
|
|
1007
|
+
p.status = next;
|
|
1008
|
+
if (next === _PM_V2.ACTIVE && !p.activatedAt) p.activatedAt = now;
|
|
1009
|
+
if (next === _PM_V2.RETIRED && !p.retiredAt) p.retiredAt = now;
|
|
1010
|
+
p.lastSeenAt = now;
|
|
1011
|
+
return _copyProviderV2(p);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
export function activateProviderV2(id) {
|
|
1015
|
+
return _transitionProviderV2(id, _PM_V2.ACTIVE);
|
|
1016
|
+
}
|
|
1017
|
+
export function deprecateProviderV2(id) {
|
|
1018
|
+
return _transitionProviderV2(id, _PM_V2.DEPRECATED);
|
|
1019
|
+
}
|
|
1020
|
+
export function retireProviderV2(id) {
|
|
1021
|
+
return _transitionProviderV2(id, _PM_V2.RETIRED);
|
|
1022
|
+
}
|
|
1023
|
+
export function touchProviderV2(id) {
|
|
1024
|
+
const p = _ssoProvidersV2.get(id);
|
|
1025
|
+
if (!p) throw new Error(`provider ${id} not found`);
|
|
1026
|
+
p.lastSeenAt = Date.now();
|
|
1027
|
+
return _copyProviderV2(p);
|
|
1028
|
+
}
|
|
1029
|
+
export function getProviderV2(id) {
|
|
1030
|
+
const p = _ssoProvidersV2.get(id);
|
|
1031
|
+
return p ? _copyProviderV2(p) : null;
|
|
1032
|
+
}
|
|
1033
|
+
export function listProvidersV2({ owner, status, protocol } = {}) {
|
|
1034
|
+
const out = [];
|
|
1035
|
+
for (const p of _ssoProvidersV2.values()) {
|
|
1036
|
+
if (owner && p.owner !== owner) continue;
|
|
1037
|
+
if (status && p.status !== status) continue;
|
|
1038
|
+
if (protocol && p.protocol !== protocol) continue;
|
|
1039
|
+
out.push(_copyProviderV2(p));
|
|
1040
|
+
}
|
|
1041
|
+
return out;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
function _pendingLoginCountForProviderV2(providerId) {
|
|
1045
|
+
let c = 0;
|
|
1046
|
+
for (const l of _ssoLoginsV2.values()) {
|
|
1047
|
+
if (l.providerId !== providerId) continue;
|
|
1048
|
+
if (l.status === _LL_V2.QUEUED || l.status === _LL_V2.AUTHENTICATING) c++;
|
|
1049
|
+
}
|
|
1050
|
+
return c;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
export function createLoginV2({ id, providerId, subject, metadata } = {}) {
|
|
1054
|
+
if (!id || typeof id !== "string") throw new Error("id required");
|
|
1055
|
+
if (!providerId || typeof providerId !== "string")
|
|
1056
|
+
throw new Error("providerId required");
|
|
1057
|
+
if (_ssoLoginsV2.has(id)) throw new Error(`login ${id} already exists`);
|
|
1058
|
+
const provider = _ssoProvidersV2.get(providerId);
|
|
1059
|
+
if (!provider) throw new Error(`provider ${providerId} not found`);
|
|
1060
|
+
if (provider.status === _PM_V2.RETIRED)
|
|
1061
|
+
throw new Error(`provider ${providerId} retired`);
|
|
1062
|
+
if (
|
|
1063
|
+
_pendingLoginCountForProviderV2(providerId) >=
|
|
1064
|
+
_ssoConfigV2.maxPendingLoginsPerProvider
|
|
1065
|
+
) {
|
|
1066
|
+
throw new Error(
|
|
1067
|
+
`provider ${providerId} pending-login cap reached (${_ssoConfigV2.maxPendingLoginsPerProvider})`,
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
const now = Date.now();
|
|
1071
|
+
const l = {
|
|
1072
|
+
id,
|
|
1073
|
+
providerId,
|
|
1074
|
+
subject: subject || "anonymous",
|
|
1075
|
+
status: _LL_V2.QUEUED,
|
|
1076
|
+
startedAt: null,
|
|
1077
|
+
settledAt: null,
|
|
1078
|
+
createdAt: now,
|
|
1079
|
+
metadata: metadata && typeof metadata === "object" ? { ...metadata } : {},
|
|
1080
|
+
};
|
|
1081
|
+
_ssoLoginsV2.set(id, l);
|
|
1082
|
+
return _copyLoginV2(l);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
function _transitionLoginV2(id, next, extra = {}) {
|
|
1086
|
+
const l = _ssoLoginsV2.get(id);
|
|
1087
|
+
if (!l) throw new Error(`login ${id} not found`);
|
|
1088
|
+
const allowed = _LL_TRANS_V2.get(l.status);
|
|
1089
|
+
if (!allowed || !allowed.has(next))
|
|
1090
|
+
throw new Error(`invalid transition ${l.status} -> ${next}`);
|
|
1091
|
+
const now = Date.now();
|
|
1092
|
+
l.status = next;
|
|
1093
|
+
if (next === _LL_V2.AUTHENTICATING && !l.startedAt) l.startedAt = now;
|
|
1094
|
+
if (_LL_TERM_V2.has(next) && !l.settledAt) l.settledAt = now;
|
|
1095
|
+
if (extra.error) l.metadata.error = extra.error;
|
|
1096
|
+
return _copyLoginV2(l);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
export function startLoginV2(id) {
|
|
1100
|
+
return _transitionLoginV2(id, _LL_V2.AUTHENTICATING);
|
|
1101
|
+
}
|
|
1102
|
+
export function completeLoginV2(id) {
|
|
1103
|
+
return _transitionLoginV2(id, _LL_V2.AUTHENTICATED);
|
|
1104
|
+
}
|
|
1105
|
+
export function failLoginV2(id, error) {
|
|
1106
|
+
return _transitionLoginV2(id, _LL_V2.FAILED, { error });
|
|
1107
|
+
}
|
|
1108
|
+
export function cancelLoginV2(id) {
|
|
1109
|
+
return _transitionLoginV2(id, _LL_V2.CANCELLED);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
export function getLoginV2(id) {
|
|
1113
|
+
const l = _ssoLoginsV2.get(id);
|
|
1114
|
+
return l ? _copyLoginV2(l) : null;
|
|
1115
|
+
}
|
|
1116
|
+
export function listLoginsV2({ providerId, status, subject } = {}) {
|
|
1117
|
+
const out = [];
|
|
1118
|
+
for (const l of _ssoLoginsV2.values()) {
|
|
1119
|
+
if (providerId && l.providerId !== providerId) continue;
|
|
1120
|
+
if (status && l.status !== status) continue;
|
|
1121
|
+
if (subject && l.subject !== subject) continue;
|
|
1122
|
+
out.push(_copyLoginV2(l));
|
|
1123
|
+
}
|
|
1124
|
+
return out;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
export function autoDeprecateIdleProvidersV2({ now } = {}) {
|
|
1128
|
+
const t = typeof now === "number" ? now : Date.now();
|
|
1129
|
+
const flipped = [];
|
|
1130
|
+
for (const p of _ssoProvidersV2.values()) {
|
|
1131
|
+
if (p.status !== _PM_V2.ACTIVE) continue;
|
|
1132
|
+
if (t - p.lastSeenAt > _ssoConfigV2.providerIdleMs) {
|
|
1133
|
+
p.status = _PM_V2.DEPRECATED;
|
|
1134
|
+
p.lastSeenAt = t;
|
|
1135
|
+
flipped.push(_copyProviderV2(p));
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
return flipped;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
export function autoFailStuckLoginsV2({ now } = {}) {
|
|
1142
|
+
const t = typeof now === "number" ? now : Date.now();
|
|
1143
|
+
const flipped = [];
|
|
1144
|
+
for (const l of _ssoLoginsV2.values()) {
|
|
1145
|
+
if (l.status !== _LL_V2.AUTHENTICATING) continue;
|
|
1146
|
+
if (l.startedAt && t - l.startedAt > _ssoConfigV2.loginStuckMs) {
|
|
1147
|
+
l.status = _LL_V2.FAILED;
|
|
1148
|
+
l.settledAt = t;
|
|
1149
|
+
l.metadata.error = "stuck-timeout";
|
|
1150
|
+
flipped.push(_copyLoginV2(l));
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return flipped;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
export function getSsoManagerStatsV2() {
|
|
1157
|
+
const providersByStatus = {};
|
|
1158
|
+
for (const s of Object.values(_PM_V2)) providersByStatus[s] = 0;
|
|
1159
|
+
for (const p of _ssoProvidersV2.values()) providersByStatus[p.status]++;
|
|
1160
|
+
const loginsByStatus = {};
|
|
1161
|
+
for (const s of Object.values(_LL_V2)) loginsByStatus[s] = 0;
|
|
1162
|
+
for (const l of _ssoLoginsV2.values()) loginsByStatus[l.status]++;
|
|
1163
|
+
return {
|
|
1164
|
+
totalProvidersV2: _ssoProvidersV2.size,
|
|
1165
|
+
totalLoginsV2: _ssoLoginsV2.size,
|
|
1166
|
+
maxActiveProvidersPerOwner: _ssoConfigV2.maxActiveProvidersPerOwner,
|
|
1167
|
+
maxPendingLoginsPerProvider: _ssoConfigV2.maxPendingLoginsPerProvider,
|
|
1168
|
+
providerIdleMs: _ssoConfigV2.providerIdleMs,
|
|
1169
|
+
loginStuckMs: _ssoConfigV2.loginStuckMs,
|
|
1170
|
+
providersByStatus,
|
|
1171
|
+
loginsByStatus,
|
|
1172
|
+
};
|
|
1173
|
+
}
|
package/src/lib/sync-manager.js
CHANGED
|
@@ -345,3 +345,329 @@ export function clearSyncData(db) {
|
|
|
345
345
|
db.prepare("DELETE FROM sync_log").run();
|
|
346
346
|
return true;
|
|
347
347
|
}
|
|
348
|
+
|
|
349
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
350
|
+
* V2 Surface — Sync Manager governance layer.
|
|
351
|
+
* Tracks tracked-resource maturity + sync-run lifecycle independent
|
|
352
|
+
* of legacy registerResource/pushResources/pullResources flows above.
|
|
353
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
354
|
+
|
|
355
|
+
export const RESOURCE_MATURITY_V2 = Object.freeze({
|
|
356
|
+
PENDING: "pending",
|
|
357
|
+
ACTIVE: "active",
|
|
358
|
+
PAUSED: "paused",
|
|
359
|
+
ARCHIVED: "archived",
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
export const SYNC_RUN_V2 = Object.freeze({
|
|
363
|
+
QUEUED: "queued",
|
|
364
|
+
RUNNING: "running",
|
|
365
|
+
SUCCEEDED: "succeeded",
|
|
366
|
+
FAILED: "failed",
|
|
367
|
+
CANCELLED: "cancelled",
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
const RESOURCE_TRANSITIONS_V2 = new Map([
|
|
371
|
+
["pending", new Set(["active", "archived"])],
|
|
372
|
+
["active", new Set(["paused", "archived"])],
|
|
373
|
+
["paused", new Set(["active", "archived"])],
|
|
374
|
+
["archived", new Set()],
|
|
375
|
+
]);
|
|
376
|
+
const RESOURCE_TERMINALS_V2 = new Set(["archived"]);
|
|
377
|
+
|
|
378
|
+
const RUN_TRANSITIONS_V2 = new Map([
|
|
379
|
+
["queued", new Set(["running", "cancelled"])],
|
|
380
|
+
["running", new Set(["succeeded", "failed", "cancelled"])],
|
|
381
|
+
["succeeded", new Set()],
|
|
382
|
+
["failed", new Set()],
|
|
383
|
+
["cancelled", new Set()],
|
|
384
|
+
]);
|
|
385
|
+
const RUN_TERMINALS_V2 = new Set(["succeeded", "failed", "cancelled"]);
|
|
386
|
+
|
|
387
|
+
export const SYNC_DEFAULT_MAX_ACTIVE_RESOURCES_PER_OWNER = 200;
|
|
388
|
+
export const SYNC_DEFAULT_MAX_RUNNING_RUNS_PER_RESOURCE = 1;
|
|
389
|
+
export const SYNC_DEFAULT_RESOURCE_IDLE_MS = 1000 * 60 * 60 * 24 * 30; // 30 days
|
|
390
|
+
export const SYNC_DEFAULT_RUN_STUCK_MS = 1000 * 60 * 15; // 15 min
|
|
391
|
+
|
|
392
|
+
const _resourcesV2 = new Map();
|
|
393
|
+
const _runsV2 = new Map();
|
|
394
|
+
let _maxActiveResourcesPerOwnerV2 = SYNC_DEFAULT_MAX_ACTIVE_RESOURCES_PER_OWNER;
|
|
395
|
+
let _maxRunningRunsPerResourceV2 = SYNC_DEFAULT_MAX_RUNNING_RUNS_PER_RESOURCE;
|
|
396
|
+
let _resourceIdleMsV2 = SYNC_DEFAULT_RESOURCE_IDLE_MS;
|
|
397
|
+
let _runStuckMsV2 = SYNC_DEFAULT_RUN_STUCK_MS;
|
|
398
|
+
|
|
399
|
+
function _posIntSyncV2(n, label) {
|
|
400
|
+
const v = Math.floor(Number(n));
|
|
401
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
402
|
+
throw new Error(`${label} must be a positive integer`);
|
|
403
|
+
return v;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export function getMaxActiveResourcesPerOwnerV2() {
|
|
407
|
+
return _maxActiveResourcesPerOwnerV2;
|
|
408
|
+
}
|
|
409
|
+
export function setMaxActiveResourcesPerOwnerV2(n) {
|
|
410
|
+
_maxActiveResourcesPerOwnerV2 = _posIntSyncV2(
|
|
411
|
+
n,
|
|
412
|
+
"maxActiveResourcesPerOwner",
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
export function getMaxRunningRunsPerResourceV2() {
|
|
416
|
+
return _maxRunningRunsPerResourceV2;
|
|
417
|
+
}
|
|
418
|
+
export function setMaxRunningRunsPerResourceV2(n) {
|
|
419
|
+
_maxRunningRunsPerResourceV2 = _posIntSyncV2(n, "maxRunningRunsPerResource");
|
|
420
|
+
}
|
|
421
|
+
export function getResourceIdleMsV2() {
|
|
422
|
+
return _resourceIdleMsV2;
|
|
423
|
+
}
|
|
424
|
+
export function setResourceIdleMsV2(n) {
|
|
425
|
+
_resourceIdleMsV2 = _posIntSyncV2(n, "resourceIdleMs");
|
|
426
|
+
}
|
|
427
|
+
export function getRunStuckMsV2() {
|
|
428
|
+
return _runStuckMsV2;
|
|
429
|
+
}
|
|
430
|
+
export function setRunStuckMsV2(n) {
|
|
431
|
+
_runStuckMsV2 = _posIntSyncV2(n, "runStuckMs");
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export function getActiveResourceCountV2(owner) {
|
|
435
|
+
let n = 0;
|
|
436
|
+
for (const r of _resourcesV2.values()) {
|
|
437
|
+
if (r.owner === owner && r.status === "active") n += 1;
|
|
438
|
+
}
|
|
439
|
+
return n;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export function getRunningRunCountV2(resourceId) {
|
|
443
|
+
let n = 0;
|
|
444
|
+
for (const j of _runsV2.values()) {
|
|
445
|
+
if (j.resourceId === resourceId && j.status === "running") n += 1;
|
|
446
|
+
}
|
|
447
|
+
return n;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function _copyResV2(r) {
|
|
451
|
+
return { ...r, metadata: { ...r.metadata } };
|
|
452
|
+
}
|
|
453
|
+
function _copyRunV2(j) {
|
|
454
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function registerResourceV2(
|
|
458
|
+
id,
|
|
459
|
+
{ owner, kind, metadata = {}, now = Date.now() } = {},
|
|
460
|
+
) {
|
|
461
|
+
if (!id || typeof id !== "string") throw new Error("id must be a string");
|
|
462
|
+
if (!owner || typeof owner !== "string")
|
|
463
|
+
throw new Error("owner must be a string");
|
|
464
|
+
if (!kind || typeof kind !== "string")
|
|
465
|
+
throw new Error("kind must be a string");
|
|
466
|
+
if (_resourcesV2.has(id)) throw new Error(`resource ${id} already exists`);
|
|
467
|
+
const r = {
|
|
468
|
+
id,
|
|
469
|
+
owner,
|
|
470
|
+
kind,
|
|
471
|
+
status: "pending",
|
|
472
|
+
createdAt: now,
|
|
473
|
+
lastSeenAt: now,
|
|
474
|
+
activatedAt: null,
|
|
475
|
+
archivedAt: null,
|
|
476
|
+
metadata: { ...metadata },
|
|
477
|
+
};
|
|
478
|
+
_resourcesV2.set(id, r);
|
|
479
|
+
return _copyResV2(r);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export function getResourceV2(id) {
|
|
483
|
+
const r = _resourcesV2.get(id);
|
|
484
|
+
return r ? _copyResV2(r) : null;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export function listResourcesV2({ owner, kind, status } = {}) {
|
|
488
|
+
const out = [];
|
|
489
|
+
for (const r of _resourcesV2.values()) {
|
|
490
|
+
if (owner && r.owner !== owner) continue;
|
|
491
|
+
if (kind && r.kind !== kind) continue;
|
|
492
|
+
if (status && r.status !== status) continue;
|
|
493
|
+
out.push(_copyResV2(r));
|
|
494
|
+
}
|
|
495
|
+
return out;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export function setResourceStatusV2(id, next, { now = Date.now() } = {}) {
|
|
499
|
+
const r = _resourcesV2.get(id);
|
|
500
|
+
if (!r) throw new Error(`resource ${id} not found`);
|
|
501
|
+
if (!RESOURCE_TRANSITIONS_V2.has(next))
|
|
502
|
+
throw new Error(`unknown resource status: ${next}`);
|
|
503
|
+
if (RESOURCE_TERMINALS_V2.has(r.status))
|
|
504
|
+
throw new Error(`resource ${id} is in terminal state ${r.status}`);
|
|
505
|
+
const allowed = RESOURCE_TRANSITIONS_V2.get(r.status);
|
|
506
|
+
if (!allowed.has(next))
|
|
507
|
+
throw new Error(`cannot transition resource from ${r.status} to ${next}`);
|
|
508
|
+
if (next === "active") {
|
|
509
|
+
if (r.status === "pending") {
|
|
510
|
+
const count = getActiveResourceCountV2(r.owner);
|
|
511
|
+
if (count >= _maxActiveResourcesPerOwnerV2)
|
|
512
|
+
throw new Error(
|
|
513
|
+
`owner ${r.owner} already at active-resource cap (${_maxActiveResourcesPerOwnerV2})`,
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
if (!r.activatedAt) r.activatedAt = now;
|
|
517
|
+
}
|
|
518
|
+
if (next === "archived" && !r.archivedAt) r.archivedAt = now;
|
|
519
|
+
r.status = next;
|
|
520
|
+
r.lastSeenAt = now;
|
|
521
|
+
return _copyResV2(r);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export function activateResourceV2(id, opts) {
|
|
525
|
+
return setResourceStatusV2(id, "active", opts);
|
|
526
|
+
}
|
|
527
|
+
export function pauseResourceV2(id, opts) {
|
|
528
|
+
return setResourceStatusV2(id, "paused", opts);
|
|
529
|
+
}
|
|
530
|
+
export function archiveResourceV2(id, opts) {
|
|
531
|
+
return setResourceStatusV2(id, "archived", opts);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export function touchResourceV2(id, { now = Date.now() } = {}) {
|
|
535
|
+
const r = _resourcesV2.get(id);
|
|
536
|
+
if (!r) throw new Error(`resource ${id} not found`);
|
|
537
|
+
r.lastSeenAt = now;
|
|
538
|
+
return _copyResV2(r);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export function createSyncRunV2(
|
|
542
|
+
id,
|
|
543
|
+
{ resourceId, kind = "push", metadata = {}, now = Date.now() } = {},
|
|
544
|
+
) {
|
|
545
|
+
if (!id || typeof id !== "string") throw new Error("id must be a string");
|
|
546
|
+
if (!resourceId || typeof resourceId !== "string")
|
|
547
|
+
throw new Error("resourceId must be a string");
|
|
548
|
+
if (_runsV2.has(id)) throw new Error(`syncRun ${id} already exists`);
|
|
549
|
+
const j = {
|
|
550
|
+
id,
|
|
551
|
+
resourceId,
|
|
552
|
+
kind,
|
|
553
|
+
status: "queued",
|
|
554
|
+
createdAt: now,
|
|
555
|
+
lastSeenAt: now,
|
|
556
|
+
startedAt: null,
|
|
557
|
+
finishedAt: null,
|
|
558
|
+
metadata: { ...metadata },
|
|
559
|
+
};
|
|
560
|
+
_runsV2.set(id, j);
|
|
561
|
+
return _copyRunV2(j);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
export function getSyncRunV2(id) {
|
|
565
|
+
const j = _runsV2.get(id);
|
|
566
|
+
return j ? _copyRunV2(j) : null;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export function listSyncRunsV2({ resourceId, status } = {}) {
|
|
570
|
+
const out = [];
|
|
571
|
+
for (const j of _runsV2.values()) {
|
|
572
|
+
if (resourceId && j.resourceId !== resourceId) continue;
|
|
573
|
+
if (status && j.status !== status) continue;
|
|
574
|
+
out.push(_copyRunV2(j));
|
|
575
|
+
}
|
|
576
|
+
return out;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
export function setSyncRunStatusV2(id, next, { now = Date.now() } = {}) {
|
|
580
|
+
const j = _runsV2.get(id);
|
|
581
|
+
if (!j) throw new Error(`syncRun ${id} not found`);
|
|
582
|
+
if (!RUN_TRANSITIONS_V2.has(next))
|
|
583
|
+
throw new Error(`unknown syncRun status: ${next}`);
|
|
584
|
+
if (RUN_TERMINALS_V2.has(j.status))
|
|
585
|
+
throw new Error(`syncRun ${id} is in terminal state ${j.status}`);
|
|
586
|
+
const allowed = RUN_TRANSITIONS_V2.get(j.status);
|
|
587
|
+
if (!allowed.has(next))
|
|
588
|
+
throw new Error(`cannot transition syncRun from ${j.status} to ${next}`);
|
|
589
|
+
if (next === "running" && j.status === "queued") {
|
|
590
|
+
const count = getRunningRunCountV2(j.resourceId);
|
|
591
|
+
if (count >= _maxRunningRunsPerResourceV2)
|
|
592
|
+
throw new Error(
|
|
593
|
+
`resource ${j.resourceId} already at running-run cap (${_maxRunningRunsPerResourceV2})`,
|
|
594
|
+
);
|
|
595
|
+
if (!j.startedAt) j.startedAt = now;
|
|
596
|
+
}
|
|
597
|
+
if (RUN_TERMINALS_V2.has(next) && !j.finishedAt) j.finishedAt = now;
|
|
598
|
+
j.status = next;
|
|
599
|
+
j.lastSeenAt = now;
|
|
600
|
+
return _copyRunV2(j);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export function startSyncRunV2(id, opts) {
|
|
604
|
+
return setSyncRunStatusV2(id, "running", opts);
|
|
605
|
+
}
|
|
606
|
+
export function succeedSyncRunV2(id, opts) {
|
|
607
|
+
return setSyncRunStatusV2(id, "succeeded", opts);
|
|
608
|
+
}
|
|
609
|
+
export function failSyncRunV2(id, opts) {
|
|
610
|
+
return setSyncRunStatusV2(id, "failed", opts);
|
|
611
|
+
}
|
|
612
|
+
export function cancelSyncRunV2(id, opts) {
|
|
613
|
+
return setSyncRunStatusV2(id, "cancelled", opts);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
export function autoArchiveIdleResourcesV2({ now = Date.now() } = {}) {
|
|
617
|
+
const flipped = [];
|
|
618
|
+
for (const r of _resourcesV2.values()) {
|
|
619
|
+
if (r.status === "archived" || r.status === "pending") continue;
|
|
620
|
+
if (now - r.lastSeenAt > _resourceIdleMsV2) {
|
|
621
|
+
r.status = "archived";
|
|
622
|
+
r.lastSeenAt = now;
|
|
623
|
+
if (!r.archivedAt) r.archivedAt = now;
|
|
624
|
+
flipped.push(_copyResV2(r));
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return flipped;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
export function autoFailStuckSyncRunsV2({ now = Date.now() } = {}) {
|
|
631
|
+
const flipped = [];
|
|
632
|
+
for (const j of _runsV2.values()) {
|
|
633
|
+
if (j.status !== "running") continue;
|
|
634
|
+
const ref = j.startedAt ?? j.lastSeenAt;
|
|
635
|
+
if (now - ref > _runStuckMsV2) {
|
|
636
|
+
j.status = "failed";
|
|
637
|
+
j.lastSeenAt = now;
|
|
638
|
+
if (!j.finishedAt) j.finishedAt = now;
|
|
639
|
+
flipped.push(_copyRunV2(j));
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return flipped;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
export function getSyncManagerStatsV2() {
|
|
646
|
+
const resourcesByStatus = {};
|
|
647
|
+
for (const v of Object.values(RESOURCE_MATURITY_V2)) resourcesByStatus[v] = 0;
|
|
648
|
+
for (const r of _resourcesV2.values()) resourcesByStatus[r.status] += 1;
|
|
649
|
+
|
|
650
|
+
const runsByStatus = {};
|
|
651
|
+
for (const v of Object.values(SYNC_RUN_V2)) runsByStatus[v] = 0;
|
|
652
|
+
for (const j of _runsV2.values()) runsByStatus[j.status] += 1;
|
|
653
|
+
|
|
654
|
+
return {
|
|
655
|
+
totalResourcesV2: _resourcesV2.size,
|
|
656
|
+
totalSyncRunsV2: _runsV2.size,
|
|
657
|
+
maxActiveResourcesPerOwner: _maxActiveResourcesPerOwnerV2,
|
|
658
|
+
maxRunningRunsPerResource: _maxRunningRunsPerResourceV2,
|
|
659
|
+
resourceIdleMs: _resourceIdleMsV2,
|
|
660
|
+
runStuckMs: _runStuckMsV2,
|
|
661
|
+
resourcesByStatus,
|
|
662
|
+
runsByStatus,
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export function _resetStateSyncManagerV2() {
|
|
667
|
+
_resourcesV2.clear();
|
|
668
|
+
_runsV2.clear();
|
|
669
|
+
_maxActiveResourcesPerOwnerV2 = SYNC_DEFAULT_MAX_ACTIVE_RESOURCES_PER_OWNER;
|
|
670
|
+
_maxRunningRunsPerResourceV2 = SYNC_DEFAULT_MAX_RUNNING_RUNS_PER_RESOURCE;
|
|
671
|
+
_resourceIdleMsV2 = SYNC_DEFAULT_RESOURCE_IDLE_MS;
|
|
672
|
+
_runStuckMsV2 = SYNC_DEFAULT_RUN_STUCK_MS;
|
|
673
|
+
}
|