chainlesschain 0.132.0 → 0.145.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/package.json +1 -1
- package/src/commands/a2a.js +230 -0
- package/src/commands/activitypub.js +191 -0
- package/src/commands/agent.js +601 -0
- package/src/commands/audit.js +206 -0
- package/src/commands/bi.js +186 -0
- package/src/commands/bm25.js +162 -0
- package/src/commands/browse.js +225 -0
- package/src/commands/ccron.js +178 -0
- package/src/commands/chat.js +207 -0
- package/src/commands/compliance.js +420 -0
- package/src/commands/compt.js +176 -0
- package/src/commands/consol.js +237 -0
- package/src/commands/cowork.js +588 -0
- package/src/commands/crosschain.js +216 -0
- package/src/commands/dao.js +216 -0
- package/src/commands/dlp.js +206 -0
- package/src/commands/economy.js +211 -0
- package/src/commands/evolution.js +209 -0
- package/src/commands/evomap.js +216 -0
- package/src/commands/fflag.js +230 -0
- package/src/commands/git.js +185 -0
- package/src/commands/hardening.js +209 -0
- package/src/commands/hmemory.js +210 -0
- package/src/commands/incentive.js +209 -0
- package/src/commands/inference.js +178 -0
- package/src/commands/itbudget.js +161 -0
- package/src/commands/kg.js +206 -0
- package/src/commands/lowcode.js +201 -0
- package/src/commands/marketplace.js +206 -0
- package/src/commands/matrix.js +214 -0
- package/src/commands/mcpscaf.js +153 -0
- package/src/commands/meminj.js +153 -0
- package/src/commands/nostr.js +213 -0
- package/src/commands/orchestrate.js +217 -0
- package/src/commands/orchgov.js +156 -0
- package/src/commands/pdfp.js +160 -0
- package/src/commands/perf.js +176 -0
- package/src/commands/perm.js +156 -0
- package/src/commands/pipeline.js +211 -0
- package/src/commands/planmode.js +154 -0
- package/src/commands/privacy.js +203 -0
- package/src/commands/promcomp.js +166 -0
- package/src/commands/recommend.js +185 -0
- package/src/commands/reputation.js +208 -0
- package/src/commands/sandbox.js +206 -0
- package/src/commands/seshhook.js +153 -0
- package/src/commands/seshsearch.js +149 -0
- package/src/commands/seshtail.js +152 -0
- package/src/commands/seshu.js +160 -0
- package/src/commands/sganal.js +172 -0
- package/src/commands/siem.js +207 -0
- package/src/commands/sla.js +212 -0
- package/src/commands/slotfill.js +154 -0
- package/src/commands/social.js +159 -0
- package/src/commands/stress.js +206 -0
- package/src/commands/svccont.js +157 -0
- package/src/commands/terraform.js +206 -0
- package/src/commands/tms.js +183 -0
- package/src/commands/topiccls.js +158 -0
- package/src/commands/uprof.js +154 -0
- package/src/commands/vcheck.js +172 -0
- package/src/commands/webfetch.js +150 -0
- package/src/commands/zkp.js +218 -0
- package/src/harness/prompt-compressor.js +331 -0
- package/src/index.js +101 -1
- package/src/lib/a2a-protocol.js +373 -0
- package/src/lib/activitypub-bridge.js +343 -0
- package/src/lib/agent-economy.js +358 -0
- package/src/lib/app-builder.js +338 -0
- package/src/lib/audit-logger.js +321 -0
- package/src/lib/autonomous-agent.js +341 -0
- package/src/lib/bi-engine.js +339 -0
- package/src/lib/bm25-search.js +333 -0
- package/src/lib/browser-automation.js +352 -0
- package/src/lib/chat-core.js +336 -0
- package/src/lib/claude-code-bridge.js +341 -0
- package/src/lib/compliance-framework-reporter.js +359 -0
- package/src/lib/compliance-manager.js +330 -0
- package/src/lib/compression-telemetry.js +333 -0
- package/src/lib/content-recommender.js +370 -0
- package/src/lib/cowork-cron.js +330 -0
- package/src/lib/cowork-learning.js +333 -0
- package/src/lib/cowork-task-runner.js +362 -0
- package/src/lib/cowork-workflow.js +327 -0
- package/src/lib/cross-chain.js +365 -0
- package/src/lib/dao-governance.js +339 -0
- package/src/lib/dlp-engine.js +343 -0
- package/src/lib/evolution-system.js +336 -0
- package/src/lib/evomap-manager.js +339 -0
- package/src/lib/execution-backend.js +351 -0
- package/src/lib/feature-flags.js +330 -0
- package/src/lib/git-integration.js +343 -0
- package/src/lib/hardening-manager.js +341 -0
- package/src/lib/hierarchical-memory.js +341 -0
- package/src/lib/inference-network.js +362 -0
- package/src/lib/iteration-budget.js +357 -0
- package/src/lib/knowledge-graph.js +333 -0
- package/src/lib/matrix-bridge.js +339 -0
- package/src/lib/mcp-scaffold.js +345 -0
- package/src/lib/memory-injection.js +320 -0
- package/src/lib/nostr-bridge.js +342 -0
- package/src/lib/orchestrator.js +350 -0
- package/src/lib/pdf-parser.js +330 -0
- package/src/lib/perf-tuning.js +364 -0
- package/src/lib/permission-engine.js +319 -0
- package/src/lib/pipeline-orchestrator.js +345 -0
- package/src/lib/plan-mode.js +328 -0
- package/src/lib/privacy-computing.js +335 -0
- package/src/lib/prompt-compressor.js +1 -10
- package/src/lib/reputation-optimizer.js +340 -0
- package/src/lib/sandbox-v2.js +327 -0
- package/src/lib/service-container.js +342 -0
- package/src/lib/session-consolidator.js +352 -0
- package/src/lib/session-hooks.js +340 -0
- package/src/lib/session-search.js +334 -0
- package/src/lib/session-tail.js +320 -0
- package/src/lib/session-usage.js +329 -0
- package/src/lib/siem-exporter.js +352 -0
- package/src/lib/skill-marketplace.js +345 -0
- package/src/lib/sla-manager.js +341 -0
- package/src/lib/slot-filler.js +333 -0
- package/src/lib/social-graph-analytics.js +327 -0
- package/src/lib/social-graph.js +304 -0
- package/src/lib/stress-tester.js +342 -0
- package/src/lib/sub-agent-registry.js +359 -0
- package/src/lib/task-model-selector.js +333 -0
- package/src/lib/terraform-manager.js +333 -0
- package/src/lib/todo-manager.js +339 -0
- package/src/lib/token-incentive.js +341 -0
- package/src/lib/topic-classifier.js +353 -0
- package/src/lib/user-profile.js +325 -0
- package/src/lib/version-checker.js +335 -0
- package/src/lib/web-fetch.js +322 -0
- package/src/lib/zkp-engine.js +342 -0
package/src/lib/app-builder.js
CHANGED
|
@@ -742,3 +742,341 @@ export function _resetV2State() {
|
|
|
742
742
|
_v2DataSources.clear();
|
|
743
743
|
_v2StatusHistory.clear();
|
|
744
744
|
}
|
|
745
|
+
|
|
746
|
+
// ===== V2 Surface: App Builder governance overlay (CLI v0.138.0) =====
|
|
747
|
+
export const APP_MATURITY_V2 = Object.freeze({
|
|
748
|
+
PENDING: "pending",
|
|
749
|
+
ACTIVE: "active",
|
|
750
|
+
PAUSED: "paused",
|
|
751
|
+
ARCHIVED: "archived",
|
|
752
|
+
});
|
|
753
|
+
export const APP_BUILD_LIFECYCLE_V2 = Object.freeze({
|
|
754
|
+
QUEUED: "queued",
|
|
755
|
+
BUILDING: "building",
|
|
756
|
+
SUCCEEDED: "succeeded",
|
|
757
|
+
FAILED: "failed",
|
|
758
|
+
CANCELLED: "cancelled",
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
const _appTrans = new Map([
|
|
762
|
+
[
|
|
763
|
+
APP_MATURITY_V2.PENDING,
|
|
764
|
+
new Set([APP_MATURITY_V2.ACTIVE, APP_MATURITY_V2.ARCHIVED]),
|
|
765
|
+
],
|
|
766
|
+
[
|
|
767
|
+
APP_MATURITY_V2.ACTIVE,
|
|
768
|
+
new Set([APP_MATURITY_V2.PAUSED, APP_MATURITY_V2.ARCHIVED]),
|
|
769
|
+
],
|
|
770
|
+
[
|
|
771
|
+
APP_MATURITY_V2.PAUSED,
|
|
772
|
+
new Set([APP_MATURITY_V2.ACTIVE, APP_MATURITY_V2.ARCHIVED]),
|
|
773
|
+
],
|
|
774
|
+
[APP_MATURITY_V2.ARCHIVED, new Set()],
|
|
775
|
+
]);
|
|
776
|
+
const _appTerminal = new Set([APP_MATURITY_V2.ARCHIVED]);
|
|
777
|
+
const _appBuildTrans = new Map([
|
|
778
|
+
[
|
|
779
|
+
APP_BUILD_LIFECYCLE_V2.QUEUED,
|
|
780
|
+
new Set([
|
|
781
|
+
APP_BUILD_LIFECYCLE_V2.BUILDING,
|
|
782
|
+
APP_BUILD_LIFECYCLE_V2.CANCELLED,
|
|
783
|
+
]),
|
|
784
|
+
],
|
|
785
|
+
[
|
|
786
|
+
APP_BUILD_LIFECYCLE_V2.BUILDING,
|
|
787
|
+
new Set([
|
|
788
|
+
APP_BUILD_LIFECYCLE_V2.SUCCEEDED,
|
|
789
|
+
APP_BUILD_LIFECYCLE_V2.FAILED,
|
|
790
|
+
APP_BUILD_LIFECYCLE_V2.CANCELLED,
|
|
791
|
+
]),
|
|
792
|
+
],
|
|
793
|
+
[APP_BUILD_LIFECYCLE_V2.SUCCEEDED, new Set()],
|
|
794
|
+
[APP_BUILD_LIFECYCLE_V2.FAILED, new Set()],
|
|
795
|
+
[APP_BUILD_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
796
|
+
]);
|
|
797
|
+
|
|
798
|
+
const _appsV2 = new Map();
|
|
799
|
+
const _appBuilds = new Map();
|
|
800
|
+
let _appMaxActivePerOwner = 10;
|
|
801
|
+
let _appMaxPendingBuildsPerApp = 20;
|
|
802
|
+
let _appIdleMs = 30 * 24 * 60 * 60 * 1000;
|
|
803
|
+
let _appBuildStuckMs = 10 * 60 * 1000;
|
|
804
|
+
|
|
805
|
+
function _appPos(n, lbl) {
|
|
806
|
+
const v = Math.floor(Number(n));
|
|
807
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
808
|
+
throw new Error(`${lbl} must be positive integer`);
|
|
809
|
+
return v;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
export function setMaxActiveAppsPerOwnerV2(n) {
|
|
813
|
+
_appMaxActivePerOwner = _appPos(n, "maxActiveAppsPerOwner");
|
|
814
|
+
}
|
|
815
|
+
export function getMaxActiveAppsPerOwnerV2() {
|
|
816
|
+
return _appMaxActivePerOwner;
|
|
817
|
+
}
|
|
818
|
+
export function setMaxPendingAppBuildsPerAppV2(n) {
|
|
819
|
+
_appMaxPendingBuildsPerApp = _appPos(n, "maxPendingAppBuildsPerApp");
|
|
820
|
+
}
|
|
821
|
+
export function getMaxPendingAppBuildsPerAppV2() {
|
|
822
|
+
return _appMaxPendingBuildsPerApp;
|
|
823
|
+
}
|
|
824
|
+
export function setAppIdleMsV2(n) {
|
|
825
|
+
_appIdleMs = _appPos(n, "appIdleMs");
|
|
826
|
+
}
|
|
827
|
+
export function getAppIdleMsV2() {
|
|
828
|
+
return _appIdleMs;
|
|
829
|
+
}
|
|
830
|
+
export function setAppBuildStuckMsV2(n) {
|
|
831
|
+
_appBuildStuckMs = _appPos(n, "appBuildStuckMs");
|
|
832
|
+
}
|
|
833
|
+
export function getAppBuildStuckMsV2() {
|
|
834
|
+
return _appBuildStuckMs;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
export function _resetStateAppBuilderV2() {
|
|
838
|
+
_appsV2.clear();
|
|
839
|
+
_appBuilds.clear();
|
|
840
|
+
_appMaxActivePerOwner = 10;
|
|
841
|
+
_appMaxPendingBuildsPerApp = 20;
|
|
842
|
+
_appIdleMs = 30 * 24 * 60 * 60 * 1000;
|
|
843
|
+
_appBuildStuckMs = 10 * 60 * 1000;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
export function registerAppV2({ id, owner, name, metadata } = {}) {
|
|
847
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
848
|
+
if (!owner || typeof owner !== "string") throw new Error("owner is required");
|
|
849
|
+
if (_appsV2.has(id)) throw new Error(`app ${id} already registered`);
|
|
850
|
+
const now = Date.now();
|
|
851
|
+
const a = {
|
|
852
|
+
id,
|
|
853
|
+
owner,
|
|
854
|
+
name: name || id,
|
|
855
|
+
status: APP_MATURITY_V2.PENDING,
|
|
856
|
+
createdAt: now,
|
|
857
|
+
updatedAt: now,
|
|
858
|
+
activatedAt: null,
|
|
859
|
+
archivedAt: null,
|
|
860
|
+
lastTouchedAt: now,
|
|
861
|
+
metadata: { ...(metadata || {}) },
|
|
862
|
+
};
|
|
863
|
+
_appsV2.set(id, a);
|
|
864
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
865
|
+
}
|
|
866
|
+
function _appCheckA(from, to) {
|
|
867
|
+
const a = _appTrans.get(from);
|
|
868
|
+
if (!a || !a.has(to))
|
|
869
|
+
throw new Error(`invalid app transition ${from} → ${to}`);
|
|
870
|
+
}
|
|
871
|
+
function _appCountActive(owner) {
|
|
872
|
+
let n = 0;
|
|
873
|
+
for (const a of _appsV2.values())
|
|
874
|
+
if (a.owner === owner && a.status === APP_MATURITY_V2.ACTIVE) n++;
|
|
875
|
+
return n;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
export function activateAppV2(id) {
|
|
879
|
+
const a = _appsV2.get(id);
|
|
880
|
+
if (!a) throw new Error(`app ${id} not found`);
|
|
881
|
+
_appCheckA(a.status, APP_MATURITY_V2.ACTIVE);
|
|
882
|
+
const recovery = a.status === APP_MATURITY_V2.PAUSED;
|
|
883
|
+
if (!recovery) {
|
|
884
|
+
const c = _appCountActive(a.owner);
|
|
885
|
+
if (c >= _appMaxActivePerOwner)
|
|
886
|
+
throw new Error(
|
|
887
|
+
`max active apps per owner (${_appMaxActivePerOwner}) reached for ${a.owner}`,
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
const now = Date.now();
|
|
891
|
+
a.status = APP_MATURITY_V2.ACTIVE;
|
|
892
|
+
a.updatedAt = now;
|
|
893
|
+
a.lastTouchedAt = now;
|
|
894
|
+
if (!a.activatedAt) a.activatedAt = now;
|
|
895
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
896
|
+
}
|
|
897
|
+
export function pauseAppV2(id) {
|
|
898
|
+
const a = _appsV2.get(id);
|
|
899
|
+
if (!a) throw new Error(`app ${id} not found`);
|
|
900
|
+
_appCheckA(a.status, APP_MATURITY_V2.PAUSED);
|
|
901
|
+
a.status = APP_MATURITY_V2.PAUSED;
|
|
902
|
+
a.updatedAt = Date.now();
|
|
903
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
904
|
+
}
|
|
905
|
+
export function archiveAppV2(id) {
|
|
906
|
+
const a = _appsV2.get(id);
|
|
907
|
+
if (!a) throw new Error(`app ${id} not found`);
|
|
908
|
+
_appCheckA(a.status, APP_MATURITY_V2.ARCHIVED);
|
|
909
|
+
const now = Date.now();
|
|
910
|
+
a.status = APP_MATURITY_V2.ARCHIVED;
|
|
911
|
+
a.updatedAt = now;
|
|
912
|
+
if (!a.archivedAt) a.archivedAt = now;
|
|
913
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
914
|
+
}
|
|
915
|
+
export function touchAppV2(id) {
|
|
916
|
+
const a = _appsV2.get(id);
|
|
917
|
+
if (!a) throw new Error(`app ${id} not found`);
|
|
918
|
+
if (_appTerminal.has(a.status))
|
|
919
|
+
throw new Error(`cannot touch terminal app ${id}`);
|
|
920
|
+
const now = Date.now();
|
|
921
|
+
a.lastTouchedAt = now;
|
|
922
|
+
a.updatedAt = now;
|
|
923
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
924
|
+
}
|
|
925
|
+
export function getAppV2(id) {
|
|
926
|
+
const a = _appsV2.get(id);
|
|
927
|
+
if (!a) return null;
|
|
928
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
929
|
+
}
|
|
930
|
+
export function listAppsV2() {
|
|
931
|
+
return [..._appsV2.values()].map((a) => ({
|
|
932
|
+
...a,
|
|
933
|
+
metadata: { ...a.metadata },
|
|
934
|
+
}));
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
function _appCountPendingBuilds(appId) {
|
|
938
|
+
let n = 0;
|
|
939
|
+
for (const b of _appBuilds.values())
|
|
940
|
+
if (
|
|
941
|
+
b.appId === appId &&
|
|
942
|
+
(b.status === APP_BUILD_LIFECYCLE_V2.QUEUED ||
|
|
943
|
+
b.status === APP_BUILD_LIFECYCLE_V2.BUILDING)
|
|
944
|
+
)
|
|
945
|
+
n++;
|
|
946
|
+
return n;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
export function createAppBuildV2({ id, appId, target, metadata } = {}) {
|
|
950
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
951
|
+
if (!appId || typeof appId !== "string") throw new Error("appId is required");
|
|
952
|
+
if (_appBuilds.has(id)) throw new Error(`app build ${id} already exists`);
|
|
953
|
+
if (!_appsV2.has(appId)) throw new Error(`app ${appId} not found`);
|
|
954
|
+
const pending = _appCountPendingBuilds(appId);
|
|
955
|
+
if (pending >= _appMaxPendingBuildsPerApp)
|
|
956
|
+
throw new Error(
|
|
957
|
+
`max pending app builds per app (${_appMaxPendingBuildsPerApp}) reached for ${appId}`,
|
|
958
|
+
);
|
|
959
|
+
const now = Date.now();
|
|
960
|
+
const b = {
|
|
961
|
+
id,
|
|
962
|
+
appId,
|
|
963
|
+
target: target || "web",
|
|
964
|
+
status: APP_BUILD_LIFECYCLE_V2.QUEUED,
|
|
965
|
+
createdAt: now,
|
|
966
|
+
updatedAt: now,
|
|
967
|
+
startedAt: null,
|
|
968
|
+
settledAt: null,
|
|
969
|
+
metadata: { ...(metadata || {}) },
|
|
970
|
+
};
|
|
971
|
+
_appBuilds.set(id, b);
|
|
972
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
973
|
+
}
|
|
974
|
+
function _appCheckB(from, to) {
|
|
975
|
+
const a = _appBuildTrans.get(from);
|
|
976
|
+
if (!a || !a.has(to))
|
|
977
|
+
throw new Error(`invalid app build transition ${from} → ${to}`);
|
|
978
|
+
}
|
|
979
|
+
export function startAppBuildV2(id) {
|
|
980
|
+
const b = _appBuilds.get(id);
|
|
981
|
+
if (!b) throw new Error(`app build ${id} not found`);
|
|
982
|
+
_appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.BUILDING);
|
|
983
|
+
const now = Date.now();
|
|
984
|
+
b.status = APP_BUILD_LIFECYCLE_V2.BUILDING;
|
|
985
|
+
b.updatedAt = now;
|
|
986
|
+
if (!b.startedAt) b.startedAt = now;
|
|
987
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
988
|
+
}
|
|
989
|
+
export function succeedAppBuildV2(id) {
|
|
990
|
+
const b = _appBuilds.get(id);
|
|
991
|
+
if (!b) throw new Error(`app build ${id} not found`);
|
|
992
|
+
_appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.SUCCEEDED);
|
|
993
|
+
const now = Date.now();
|
|
994
|
+
b.status = APP_BUILD_LIFECYCLE_V2.SUCCEEDED;
|
|
995
|
+
b.updatedAt = now;
|
|
996
|
+
if (!b.settledAt) b.settledAt = now;
|
|
997
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
998
|
+
}
|
|
999
|
+
export function failAppBuildV2(id, reason) {
|
|
1000
|
+
const b = _appBuilds.get(id);
|
|
1001
|
+
if (!b) throw new Error(`app build ${id} not found`);
|
|
1002
|
+
_appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.FAILED);
|
|
1003
|
+
const now = Date.now();
|
|
1004
|
+
b.status = APP_BUILD_LIFECYCLE_V2.FAILED;
|
|
1005
|
+
b.updatedAt = now;
|
|
1006
|
+
if (!b.settledAt) b.settledAt = now;
|
|
1007
|
+
if (reason) b.metadata.failReason = String(reason);
|
|
1008
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
1009
|
+
}
|
|
1010
|
+
export function cancelAppBuildV2(id, reason) {
|
|
1011
|
+
const b = _appBuilds.get(id);
|
|
1012
|
+
if (!b) throw new Error(`app build ${id} not found`);
|
|
1013
|
+
_appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.CANCELLED);
|
|
1014
|
+
const now = Date.now();
|
|
1015
|
+
b.status = APP_BUILD_LIFECYCLE_V2.CANCELLED;
|
|
1016
|
+
b.updatedAt = now;
|
|
1017
|
+
if (!b.settledAt) b.settledAt = now;
|
|
1018
|
+
if (reason) b.metadata.cancelReason = String(reason);
|
|
1019
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
1020
|
+
}
|
|
1021
|
+
export function getAppBuildV2(id) {
|
|
1022
|
+
const b = _appBuilds.get(id);
|
|
1023
|
+
if (!b) return null;
|
|
1024
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
1025
|
+
}
|
|
1026
|
+
export function listAppBuildsV2() {
|
|
1027
|
+
return [..._appBuilds.values()].map((b) => ({
|
|
1028
|
+
...b,
|
|
1029
|
+
metadata: { ...b.metadata },
|
|
1030
|
+
}));
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
export function autoPauseIdleAppsV2({ now } = {}) {
|
|
1034
|
+
const t = now ?? Date.now();
|
|
1035
|
+
const flipped = [];
|
|
1036
|
+
for (const a of _appsV2.values())
|
|
1037
|
+
if (
|
|
1038
|
+
a.status === APP_MATURITY_V2.ACTIVE &&
|
|
1039
|
+
t - a.lastTouchedAt >= _appIdleMs
|
|
1040
|
+
) {
|
|
1041
|
+
a.status = APP_MATURITY_V2.PAUSED;
|
|
1042
|
+
a.updatedAt = t;
|
|
1043
|
+
flipped.push(a.id);
|
|
1044
|
+
}
|
|
1045
|
+
return { flipped, count: flipped.length };
|
|
1046
|
+
}
|
|
1047
|
+
export function autoFailStuckAppBuildsV2({ now } = {}) {
|
|
1048
|
+
const t = now ?? Date.now();
|
|
1049
|
+
const flipped = [];
|
|
1050
|
+
for (const b of _appBuilds.values())
|
|
1051
|
+
if (
|
|
1052
|
+
b.status === APP_BUILD_LIFECYCLE_V2.BUILDING &&
|
|
1053
|
+
b.startedAt != null &&
|
|
1054
|
+
t - b.startedAt >= _appBuildStuckMs
|
|
1055
|
+
) {
|
|
1056
|
+
b.status = APP_BUILD_LIFECYCLE_V2.FAILED;
|
|
1057
|
+
b.updatedAt = t;
|
|
1058
|
+
if (!b.settledAt) b.settledAt = t;
|
|
1059
|
+
b.metadata.failReason = "auto-fail-stuck";
|
|
1060
|
+
flipped.push(b.id);
|
|
1061
|
+
}
|
|
1062
|
+
return { flipped, count: flipped.length };
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
export function getAppBuilderGovStatsV2() {
|
|
1066
|
+
const appsByStatus = {};
|
|
1067
|
+
for (const s of Object.values(APP_MATURITY_V2)) appsByStatus[s] = 0;
|
|
1068
|
+
for (const a of _appsV2.values()) appsByStatus[a.status]++;
|
|
1069
|
+
const buildsByStatus = {};
|
|
1070
|
+
for (const s of Object.values(APP_BUILD_LIFECYCLE_V2)) buildsByStatus[s] = 0;
|
|
1071
|
+
for (const b of _appBuilds.values()) buildsByStatus[b.status]++;
|
|
1072
|
+
return {
|
|
1073
|
+
totalAppsV2: _appsV2.size,
|
|
1074
|
+
totalAppBuildsV2: _appBuilds.size,
|
|
1075
|
+
maxActiveAppsPerOwner: _appMaxActivePerOwner,
|
|
1076
|
+
maxPendingAppBuildsPerApp: _appMaxPendingBuildsPerApp,
|
|
1077
|
+
appIdleMs: _appIdleMs,
|
|
1078
|
+
appBuildStuckMs: _appBuildStuckMs,
|
|
1079
|
+
appsByStatus,
|
|
1080
|
+
buildsByStatus,
|
|
1081
|
+
};
|
|
1082
|
+
}
|
package/src/lib/audit-logger.js
CHANGED
|
@@ -741,3 +741,324 @@ export function _resetStateV2() {
|
|
|
741
741
|
_archiveRetentionMs = AUDIT_DEFAULT_ARCHIVE_RETENTION_MS;
|
|
742
742
|
_purgeRetentionMs = AUDIT_DEFAULT_PURGE_RETENTION_MS;
|
|
743
743
|
}
|
|
744
|
+
|
|
745
|
+
// =====================================================================
|
|
746
|
+
// audit-logger V2 governance overlay (iter16)
|
|
747
|
+
// =====================================================================
|
|
748
|
+
export const AUD_PROFILE_MATURITY_V2 = Object.freeze({
|
|
749
|
+
PENDING: "pending",
|
|
750
|
+
ACTIVE: "active",
|
|
751
|
+
SUSPENDED: "suspended",
|
|
752
|
+
ARCHIVED: "archived",
|
|
753
|
+
});
|
|
754
|
+
export const AUD_WRITE_LIFECYCLE_V2 = Object.freeze({
|
|
755
|
+
QUEUED: "queued",
|
|
756
|
+
WRITING: "writing",
|
|
757
|
+
WRITTEN: "written",
|
|
758
|
+
FAILED: "failed",
|
|
759
|
+
CANCELLED: "cancelled",
|
|
760
|
+
});
|
|
761
|
+
const _audPTrans = new Map([
|
|
762
|
+
[
|
|
763
|
+
AUD_PROFILE_MATURITY_V2.PENDING,
|
|
764
|
+
new Set([AUD_PROFILE_MATURITY_V2.ACTIVE, AUD_PROFILE_MATURITY_V2.ARCHIVED]),
|
|
765
|
+
],
|
|
766
|
+
[
|
|
767
|
+
AUD_PROFILE_MATURITY_V2.ACTIVE,
|
|
768
|
+
new Set([
|
|
769
|
+
AUD_PROFILE_MATURITY_V2.SUSPENDED,
|
|
770
|
+
AUD_PROFILE_MATURITY_V2.ARCHIVED,
|
|
771
|
+
]),
|
|
772
|
+
],
|
|
773
|
+
[
|
|
774
|
+
AUD_PROFILE_MATURITY_V2.SUSPENDED,
|
|
775
|
+
new Set([AUD_PROFILE_MATURITY_V2.ACTIVE, AUD_PROFILE_MATURITY_V2.ARCHIVED]),
|
|
776
|
+
],
|
|
777
|
+
[AUD_PROFILE_MATURITY_V2.ARCHIVED, new Set()],
|
|
778
|
+
]);
|
|
779
|
+
const _audPTerminal = new Set([AUD_PROFILE_MATURITY_V2.ARCHIVED]);
|
|
780
|
+
const _audJTrans = new Map([
|
|
781
|
+
[
|
|
782
|
+
AUD_WRITE_LIFECYCLE_V2.QUEUED,
|
|
783
|
+
new Set([AUD_WRITE_LIFECYCLE_V2.WRITING, AUD_WRITE_LIFECYCLE_V2.CANCELLED]),
|
|
784
|
+
],
|
|
785
|
+
[
|
|
786
|
+
AUD_WRITE_LIFECYCLE_V2.WRITING,
|
|
787
|
+
new Set([
|
|
788
|
+
AUD_WRITE_LIFECYCLE_V2.WRITTEN,
|
|
789
|
+
AUD_WRITE_LIFECYCLE_V2.FAILED,
|
|
790
|
+
AUD_WRITE_LIFECYCLE_V2.CANCELLED,
|
|
791
|
+
]),
|
|
792
|
+
],
|
|
793
|
+
[AUD_WRITE_LIFECYCLE_V2.WRITTEN, new Set()],
|
|
794
|
+
[AUD_WRITE_LIFECYCLE_V2.FAILED, new Set()],
|
|
795
|
+
[AUD_WRITE_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
796
|
+
]);
|
|
797
|
+
const _audPsV2 = new Map();
|
|
798
|
+
const _audJsV2 = new Map();
|
|
799
|
+
let _audMaxActive = 8,
|
|
800
|
+
_audMaxPending = 30,
|
|
801
|
+
_audIdleMs = 30 * 24 * 60 * 60 * 1000,
|
|
802
|
+
_audStuckMs = 60 * 1000;
|
|
803
|
+
function _audPos(n, label) {
|
|
804
|
+
const v = Math.floor(Number(n));
|
|
805
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
806
|
+
throw new Error(`${label} must be positive integer`);
|
|
807
|
+
return v;
|
|
808
|
+
}
|
|
809
|
+
function _audCheckP(from, to) {
|
|
810
|
+
const a = _audPTrans.get(from);
|
|
811
|
+
if (!a || !a.has(to))
|
|
812
|
+
throw new Error(`invalid aud profile transition ${from} → ${to}`);
|
|
813
|
+
}
|
|
814
|
+
function _audCheckJ(from, to) {
|
|
815
|
+
const a = _audJTrans.get(from);
|
|
816
|
+
if (!a || !a.has(to))
|
|
817
|
+
throw new Error(`invalid aud write transition ${from} → ${to}`);
|
|
818
|
+
}
|
|
819
|
+
function _audCountActive(owner) {
|
|
820
|
+
let c = 0;
|
|
821
|
+
for (const p of _audPsV2.values())
|
|
822
|
+
if (p.owner === owner && p.status === AUD_PROFILE_MATURITY_V2.ACTIVE) c++;
|
|
823
|
+
return c;
|
|
824
|
+
}
|
|
825
|
+
function _audCountPending(profileId) {
|
|
826
|
+
let c = 0;
|
|
827
|
+
for (const j of _audJsV2.values())
|
|
828
|
+
if (
|
|
829
|
+
j.profileId === profileId &&
|
|
830
|
+
(j.status === AUD_WRITE_LIFECYCLE_V2.QUEUED ||
|
|
831
|
+
j.status === AUD_WRITE_LIFECYCLE_V2.WRITING)
|
|
832
|
+
)
|
|
833
|
+
c++;
|
|
834
|
+
return c;
|
|
835
|
+
}
|
|
836
|
+
export function setMaxActiveAudProfilesPerOwnerV2(n) {
|
|
837
|
+
_audMaxActive = _audPos(n, "maxActiveAudProfilesPerOwner");
|
|
838
|
+
}
|
|
839
|
+
export function getMaxActiveAudProfilesPerOwnerV2() {
|
|
840
|
+
return _audMaxActive;
|
|
841
|
+
}
|
|
842
|
+
export function setMaxPendingAudWritesPerProfileV2(n) {
|
|
843
|
+
_audMaxPending = _audPos(n, "maxPendingAudWritesPerProfile");
|
|
844
|
+
}
|
|
845
|
+
export function getMaxPendingAudWritesPerProfileV2() {
|
|
846
|
+
return _audMaxPending;
|
|
847
|
+
}
|
|
848
|
+
export function setAudProfileIdleMsV2(n) {
|
|
849
|
+
_audIdleMs = _audPos(n, "audProfileIdleMs");
|
|
850
|
+
}
|
|
851
|
+
export function getAudProfileIdleMsV2() {
|
|
852
|
+
return _audIdleMs;
|
|
853
|
+
}
|
|
854
|
+
export function setAudWriteStuckMsV2(n) {
|
|
855
|
+
_audStuckMs = _audPos(n, "audWriteStuckMs");
|
|
856
|
+
}
|
|
857
|
+
export function getAudWriteStuckMsV2() {
|
|
858
|
+
return _audStuckMs;
|
|
859
|
+
}
|
|
860
|
+
export function _resetStateAuditLoggerV2() {
|
|
861
|
+
_audPsV2.clear();
|
|
862
|
+
_audJsV2.clear();
|
|
863
|
+
_audMaxActive = 8;
|
|
864
|
+
_audMaxPending = 30;
|
|
865
|
+
_audIdleMs = 30 * 24 * 60 * 60 * 1000;
|
|
866
|
+
_audStuckMs = 60 * 1000;
|
|
867
|
+
}
|
|
868
|
+
export function registerAudProfileV2({ id, owner, level, metadata } = {}) {
|
|
869
|
+
if (!id || !owner) throw new Error("id and owner required");
|
|
870
|
+
if (_audPsV2.has(id)) throw new Error(`aud profile ${id} already exists`);
|
|
871
|
+
const now = Date.now();
|
|
872
|
+
const p = {
|
|
873
|
+
id,
|
|
874
|
+
owner,
|
|
875
|
+
level: level || "info",
|
|
876
|
+
status: AUD_PROFILE_MATURITY_V2.PENDING,
|
|
877
|
+
createdAt: now,
|
|
878
|
+
updatedAt: now,
|
|
879
|
+
lastTouchedAt: now,
|
|
880
|
+
activatedAt: null,
|
|
881
|
+
archivedAt: null,
|
|
882
|
+
metadata: { ...(metadata || {}) },
|
|
883
|
+
};
|
|
884
|
+
_audPsV2.set(id, p);
|
|
885
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
886
|
+
}
|
|
887
|
+
export function activateAudProfileV2(id) {
|
|
888
|
+
const p = _audPsV2.get(id);
|
|
889
|
+
if (!p) throw new Error(`aud profile ${id} not found`);
|
|
890
|
+
const isInitial = p.status === AUD_PROFILE_MATURITY_V2.PENDING;
|
|
891
|
+
_audCheckP(p.status, AUD_PROFILE_MATURITY_V2.ACTIVE);
|
|
892
|
+
if (isInitial && _audCountActive(p.owner) >= _audMaxActive)
|
|
893
|
+
throw new Error(`max active aud profiles for owner ${p.owner} reached`);
|
|
894
|
+
const now = Date.now();
|
|
895
|
+
p.status = AUD_PROFILE_MATURITY_V2.ACTIVE;
|
|
896
|
+
p.updatedAt = now;
|
|
897
|
+
p.lastTouchedAt = now;
|
|
898
|
+
if (!p.activatedAt) p.activatedAt = now;
|
|
899
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
900
|
+
}
|
|
901
|
+
export function suspendAudProfileV2(id) {
|
|
902
|
+
const p = _audPsV2.get(id);
|
|
903
|
+
if (!p) throw new Error(`aud profile ${id} not found`);
|
|
904
|
+
_audCheckP(p.status, AUD_PROFILE_MATURITY_V2.SUSPENDED);
|
|
905
|
+
p.status = AUD_PROFILE_MATURITY_V2.SUSPENDED;
|
|
906
|
+
p.updatedAt = Date.now();
|
|
907
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
908
|
+
}
|
|
909
|
+
export function archiveAudProfileV2(id) {
|
|
910
|
+
const p = _audPsV2.get(id);
|
|
911
|
+
if (!p) throw new Error(`aud profile ${id} not found`);
|
|
912
|
+
_audCheckP(p.status, AUD_PROFILE_MATURITY_V2.ARCHIVED);
|
|
913
|
+
const now = Date.now();
|
|
914
|
+
p.status = AUD_PROFILE_MATURITY_V2.ARCHIVED;
|
|
915
|
+
p.updatedAt = now;
|
|
916
|
+
if (!p.archivedAt) p.archivedAt = now;
|
|
917
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
918
|
+
}
|
|
919
|
+
export function touchAudProfileV2(id) {
|
|
920
|
+
const p = _audPsV2.get(id);
|
|
921
|
+
if (!p) throw new Error(`aud profile ${id} not found`);
|
|
922
|
+
if (_audPTerminal.has(p.status))
|
|
923
|
+
throw new Error(`cannot touch terminal aud profile ${id}`);
|
|
924
|
+
const now = Date.now();
|
|
925
|
+
p.lastTouchedAt = now;
|
|
926
|
+
p.updatedAt = now;
|
|
927
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
928
|
+
}
|
|
929
|
+
export function getAudProfileV2(id) {
|
|
930
|
+
const p = _audPsV2.get(id);
|
|
931
|
+
if (!p) return null;
|
|
932
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
933
|
+
}
|
|
934
|
+
export function listAudProfilesV2() {
|
|
935
|
+
return [..._audPsV2.values()].map((p) => ({
|
|
936
|
+
...p,
|
|
937
|
+
metadata: { ...p.metadata },
|
|
938
|
+
}));
|
|
939
|
+
}
|
|
940
|
+
export function createAudWriteV2({ id, profileId, key, metadata } = {}) {
|
|
941
|
+
if (!id || !profileId) throw new Error("id and profileId required");
|
|
942
|
+
if (_audJsV2.has(id)) throw new Error(`aud write ${id} already exists`);
|
|
943
|
+
if (!_audPsV2.has(profileId))
|
|
944
|
+
throw new Error(`aud profile ${profileId} not found`);
|
|
945
|
+
if (_audCountPending(profileId) >= _audMaxPending)
|
|
946
|
+
throw new Error(`max pending aud writes for profile ${profileId} reached`);
|
|
947
|
+
const now = Date.now();
|
|
948
|
+
const j = {
|
|
949
|
+
id,
|
|
950
|
+
profileId,
|
|
951
|
+
key: key || "",
|
|
952
|
+
status: AUD_WRITE_LIFECYCLE_V2.QUEUED,
|
|
953
|
+
createdAt: now,
|
|
954
|
+
updatedAt: now,
|
|
955
|
+
startedAt: null,
|
|
956
|
+
settledAt: null,
|
|
957
|
+
metadata: { ...(metadata || {}) },
|
|
958
|
+
};
|
|
959
|
+
_audJsV2.set(id, j);
|
|
960
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
961
|
+
}
|
|
962
|
+
export function writingAudWriteV2(id) {
|
|
963
|
+
const j = _audJsV2.get(id);
|
|
964
|
+
if (!j) throw new Error(`aud write ${id} not found`);
|
|
965
|
+
_audCheckJ(j.status, AUD_WRITE_LIFECYCLE_V2.WRITING);
|
|
966
|
+
const now = Date.now();
|
|
967
|
+
j.status = AUD_WRITE_LIFECYCLE_V2.WRITING;
|
|
968
|
+
j.updatedAt = now;
|
|
969
|
+
if (!j.startedAt) j.startedAt = now;
|
|
970
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
971
|
+
}
|
|
972
|
+
export function writeOkAudV2(id) {
|
|
973
|
+
const j = _audJsV2.get(id);
|
|
974
|
+
if (!j) throw new Error(`aud write ${id} not found`);
|
|
975
|
+
_audCheckJ(j.status, AUD_WRITE_LIFECYCLE_V2.WRITTEN);
|
|
976
|
+
const now = Date.now();
|
|
977
|
+
j.status = AUD_WRITE_LIFECYCLE_V2.WRITTEN;
|
|
978
|
+
j.updatedAt = now;
|
|
979
|
+
if (!j.settledAt) j.settledAt = now;
|
|
980
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
981
|
+
}
|
|
982
|
+
export function failAudWriteV2(id, reason) {
|
|
983
|
+
const j = _audJsV2.get(id);
|
|
984
|
+
if (!j) throw new Error(`aud write ${id} not found`);
|
|
985
|
+
_audCheckJ(j.status, AUD_WRITE_LIFECYCLE_V2.FAILED);
|
|
986
|
+
const now = Date.now();
|
|
987
|
+
j.status = AUD_WRITE_LIFECYCLE_V2.FAILED;
|
|
988
|
+
j.updatedAt = now;
|
|
989
|
+
if (!j.settledAt) j.settledAt = now;
|
|
990
|
+
if (reason) j.metadata.failReason = String(reason);
|
|
991
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
992
|
+
}
|
|
993
|
+
export function cancelAudWriteV2(id, reason) {
|
|
994
|
+
const j = _audJsV2.get(id);
|
|
995
|
+
if (!j) throw new Error(`aud write ${id} not found`);
|
|
996
|
+
_audCheckJ(j.status, AUD_WRITE_LIFECYCLE_V2.CANCELLED);
|
|
997
|
+
const now = Date.now();
|
|
998
|
+
j.status = AUD_WRITE_LIFECYCLE_V2.CANCELLED;
|
|
999
|
+
j.updatedAt = now;
|
|
1000
|
+
if (!j.settledAt) j.settledAt = now;
|
|
1001
|
+
if (reason) j.metadata.cancelReason = String(reason);
|
|
1002
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
1003
|
+
}
|
|
1004
|
+
export function getAudWriteV2(id) {
|
|
1005
|
+
const j = _audJsV2.get(id);
|
|
1006
|
+
if (!j) return null;
|
|
1007
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
1008
|
+
}
|
|
1009
|
+
export function listAudWritesV2() {
|
|
1010
|
+
return [..._audJsV2.values()].map((j) => ({
|
|
1011
|
+
...j,
|
|
1012
|
+
metadata: { ...j.metadata },
|
|
1013
|
+
}));
|
|
1014
|
+
}
|
|
1015
|
+
export function autoSuspendIdleAudProfilesV2({ now } = {}) {
|
|
1016
|
+
const t = now ?? Date.now();
|
|
1017
|
+
const flipped = [];
|
|
1018
|
+
for (const p of _audPsV2.values())
|
|
1019
|
+
if (
|
|
1020
|
+
p.status === AUD_PROFILE_MATURITY_V2.ACTIVE &&
|
|
1021
|
+
t - p.lastTouchedAt >= _audIdleMs
|
|
1022
|
+
) {
|
|
1023
|
+
p.status = AUD_PROFILE_MATURITY_V2.SUSPENDED;
|
|
1024
|
+
p.updatedAt = t;
|
|
1025
|
+
flipped.push(p.id);
|
|
1026
|
+
}
|
|
1027
|
+
return { flipped, count: flipped.length };
|
|
1028
|
+
}
|
|
1029
|
+
export function autoFailStuckAudWritesV2({ now } = {}) {
|
|
1030
|
+
const t = now ?? Date.now();
|
|
1031
|
+
const flipped = [];
|
|
1032
|
+
for (const j of _audJsV2.values())
|
|
1033
|
+
if (
|
|
1034
|
+
j.status === AUD_WRITE_LIFECYCLE_V2.WRITING &&
|
|
1035
|
+
j.startedAt != null &&
|
|
1036
|
+
t - j.startedAt >= _audStuckMs
|
|
1037
|
+
) {
|
|
1038
|
+
j.status = AUD_WRITE_LIFECYCLE_V2.FAILED;
|
|
1039
|
+
j.updatedAt = t;
|
|
1040
|
+
if (!j.settledAt) j.settledAt = t;
|
|
1041
|
+
j.metadata.failReason = "auto-fail-stuck";
|
|
1042
|
+
flipped.push(j.id);
|
|
1043
|
+
}
|
|
1044
|
+
return { flipped, count: flipped.length };
|
|
1045
|
+
}
|
|
1046
|
+
export function getAuditLoggerGovStatsV2() {
|
|
1047
|
+
const profilesByStatus = {};
|
|
1048
|
+
for (const v of Object.values(AUD_PROFILE_MATURITY_V2))
|
|
1049
|
+
profilesByStatus[v] = 0;
|
|
1050
|
+
for (const p of _audPsV2.values()) profilesByStatus[p.status]++;
|
|
1051
|
+
const writesByStatus = {};
|
|
1052
|
+
for (const v of Object.values(AUD_WRITE_LIFECYCLE_V2)) writesByStatus[v] = 0;
|
|
1053
|
+
for (const j of _audJsV2.values()) writesByStatus[j.status]++;
|
|
1054
|
+
return {
|
|
1055
|
+
totalAudProfilesV2: _audPsV2.size,
|
|
1056
|
+
totalAudWritesV2: _audJsV2.size,
|
|
1057
|
+
maxActiveAudProfilesPerOwner: _audMaxActive,
|
|
1058
|
+
maxPendingAudWritesPerProfile: _audMaxPending,
|
|
1059
|
+
audProfileIdleMs: _audIdleMs,
|
|
1060
|
+
audWriteStuckMs: _audStuckMs,
|
|
1061
|
+
profilesByStatus,
|
|
1062
|
+
writesByStatus,
|
|
1063
|
+
};
|
|
1064
|
+
}
|