aimeat 1.4.8 → 1.6.1
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/.env.example +15 -0
- package/dist/bin/aimeat.js +0 -0
- package/dist/locales/en.json +139 -6
- package/dist/locales/fi.json +139 -6
- package/dist/public/css/views/admin.css +97 -0
- package/dist/public/css/views/profile.css +37 -0
- package/dist/public/js/services/admin.js +12 -1
- package/dist/public/js/services/boards.js +6 -3
- package/dist/public/js/services/memory.js +10 -0
- package/dist/public/views/admin/federation-tab.js +153 -7
- package/dist/public/views/admin/ghii-tab.js +2 -0
- package/dist/public/views/admin/stats-tab.js +480 -187
- package/dist/public/views/admin.js +1 -1
- package/dist/public/views/profile/access-tab.js +161 -58
- package/dist/public/views/profile/agents-tab.js +13 -1
- package/dist/public/views/profile/boards-tab.js +12 -0
- package/dist/public/views/profile/data-wallet-tab.js +29 -2
- package/dist/public/views/profile/knowledge-tab.js +64 -2
- package/dist/public/views/profile/landing-page.js +9 -6
- package/dist/public/views/profile/memory-tab.js +92 -4
- package/dist/src/auth/jwt.d.ts +6 -0
- package/dist/src/auth/jwt.d.ts.map +1 -1
- package/dist/src/auth/jwt.js +6 -0
- package/dist/src/auth/jwt.js.map +1 -1
- package/dist/src/auth/middleware.d.ts +7 -0
- package/dist/src/auth/middleware.d.ts.map +1 -1
- package/dist/src/auth/middleware.js +20 -0
- package/dist/src/auth/middleware.js.map +1 -1
- package/dist/src/auth/node-keys.d.ts.map +1 -1
- package/dist/src/auth/node-keys.js +3 -0
- package/dist/src/auth/node-keys.js.map +1 -1
- package/dist/src/config.d.ts +13 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +14 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/index.js +41 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/extensions.js +1 -1
- package/dist/src/mcp/extensions.js.map +1 -1
- package/dist/src/middleware/federation-proxy.d.ts +35 -0
- package/dist/src/middleware/federation-proxy.d.ts.map +1 -0
- package/dist/src/middleware/federation-proxy.js +92 -0
- package/dist/src/middleware/federation-proxy.js.map +1 -0
- package/dist/src/middleware/rate-limit.d.ts.map +1 -1
- package/dist/src/middleware/rate-limit.js +4 -1
- package/dist/src/middleware/rate-limit.js.map +1 -1
- package/dist/src/models/schemas.d.ts +45 -0
- package/dist/src/models/schemas.d.ts.map +1 -1
- package/dist/src/models/schemas.js +37 -1
- package/dist/src/models/schemas.js.map +1 -1
- package/dist/src/routes/actions.d.ts.map +1 -1
- package/dist/src/routes/actions.js +8 -2
- package/dist/src/routes/actions.js.map +1 -1
- package/dist/src/routes/admin-agents.d.ts.map +1 -1
- package/dist/src/routes/admin-agents.js +1 -0
- package/dist/src/routes/admin-agents.js.map +1 -1
- package/dist/src/routes/admin-features.d.ts.map +1 -1
- package/dist/src/routes/admin-features.js +2 -0
- package/dist/src/routes/admin-features.js.map +1 -1
- package/dist/src/routes/admin-monitoring.d.ts.map +1 -1
- package/dist/src/routes/admin-monitoring.js +7 -0
- package/dist/src/routes/admin-monitoring.js.map +1 -1
- package/dist/src/routes/admin.d.ts.map +1 -1
- package/dist/src/routes/admin.js +33 -15
- package/dist/src/routes/admin.js.map +1 -1
- package/dist/src/routes/agents.d.ts.map +1 -1
- package/dist/src/routes/agents.js +38 -5
- package/dist/src/routes/agents.js.map +1 -1
- package/dist/src/routes/apps.d.ts.map +1 -1
- package/dist/src/routes/apps.js +5 -1
- package/dist/src/routes/apps.js.map +1 -1
- package/dist/src/routes/auth.d.ts.map +1 -1
- package/dist/src/routes/auth.js +19 -1
- package/dist/src/routes/auth.js.map +1 -1
- package/dist/src/routes/boards.d.ts.map +1 -1
- package/dist/src/routes/boards.js +14 -7
- package/dist/src/routes/boards.js.map +1 -1
- package/dist/src/routes/consent.d.ts.map +1 -1
- package/dist/src/routes/consent.js +2 -1
- package/dist/src/routes/consent.js.map +1 -1
- package/dist/src/routes/disputes.js +4 -4
- package/dist/src/routes/disputes.js.map +1 -1
- package/dist/src/routes/extensions.d.ts.map +1 -1
- package/dist/src/routes/extensions.js +72 -21
- package/dist/src/routes/extensions.js.map +1 -1
- package/dist/src/routes/federation-auth.d.ts +15 -0
- package/dist/src/routes/federation-auth.d.ts.map +1 -0
- package/dist/src/routes/federation-auth.js +122 -0
- package/dist/src/routes/federation-auth.js.map +1 -0
- package/dist/src/routes/federation-genesis.d.ts +2 -1
- package/dist/src/routes/federation-genesis.d.ts.map +1 -1
- package/dist/src/routes/federation-genesis.js +58 -2
- package/dist/src/routes/federation-genesis.js.map +1 -1
- package/dist/src/routes/federation-peer.d.ts.map +1 -1
- package/dist/src/routes/federation-peer.js +91 -2
- package/dist/src/routes/federation-peer.js.map +1 -1
- package/dist/src/routes/federation-sync.d.ts.map +1 -1
- package/dist/src/routes/federation-sync.js +14 -1
- package/dist/src/routes/federation-sync.js.map +1 -1
- package/dist/src/routes/federation.d.ts +2 -1
- package/dist/src/routes/federation.d.ts.map +1 -1
- package/dist/src/routes/federation.js +4 -2
- package/dist/src/routes/federation.js.map +1 -1
- package/dist/src/routes/flags.d.ts.map +1 -1
- package/dist/src/routes/flags.js +2 -1
- package/dist/src/routes/flags.js.map +1 -1
- package/dist/src/routes/foundry.d.ts.map +1 -1
- package/dist/src/routes/foundry.js +2 -2
- package/dist/src/routes/foundry.js.map +1 -1
- package/dist/src/routes/generator.d.ts.map +1 -1
- package/dist/src/routes/generator.js +2 -2
- package/dist/src/routes/generator.js.map +1 -1
- package/dist/src/routes/ghii.d.ts +2 -1
- package/dist/src/routes/ghii.d.ts.map +1 -1
- package/dist/src/routes/ghii.js +154 -34
- package/dist/src/routes/ghii.js.map +1 -1
- package/dist/src/routes/libs.js +42 -10
- package/dist/src/routes/libs.js.map +1 -1
- package/dist/src/routes/memory.d.ts.map +1 -1
- package/dist/src/routes/memory.js +164 -0
- package/dist/src/routes/memory.js.map +1 -1
- package/dist/src/routes/owners.d.ts.map +1 -1
- package/dist/src/routes/owners.js +104 -8
- package/dist/src/routes/owners.js.map +1 -1
- package/dist/src/routes/packages.js +1 -1
- package/dist/src/routes/packages.js.map +1 -1
- package/dist/src/routes/stats.d.ts +13 -0
- package/dist/src/routes/stats.d.ts.map +1 -1
- package/dist/src/routes/stats.js +54 -4
- package/dist/src/routes/stats.js.map +1 -1
- package/dist/src/routes/storage-files.d.ts.map +1 -1
- package/dist/src/routes/storage-files.js +5 -1
- package/dist/src/routes/storage-files.js.map +1 -1
- package/dist/src/routes/upload.js +2 -2
- package/dist/src/routes/upload.js.map +1 -1
- package/dist/src/routes/wallet.d.ts.map +1 -1
- package/dist/src/routes/wallet.js +2 -1
- package/dist/src/routes/wallet.js.map +1 -1
- package/dist/src/routes/work.d.ts.map +1 -1
- package/dist/src/routes/work.js +2 -1
- package/dist/src/routes/work.js.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts +3 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.js +10 -7
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
- package/dist/src/server-bootstrap/service-init.d.ts +2 -0
- package/dist/src/server-bootstrap/service-init.d.ts.map +1 -1
- package/dist/src/server-bootstrap/service-init.js +10 -1
- package/dist/src/server-bootstrap/service-init.js.map +1 -1
- package/dist/src/server-bootstrap/static-files.d.ts.map +1 -1
- package/dist/src/server-bootstrap/static-files.js +10 -7
- package/dist/src/server-bootstrap/static-files.js.map +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +5 -2
- package/dist/src/server.js.map +1 -1
- package/dist/src/services/capability-invoke.d.ts.map +1 -1
- package/dist/src/services/capability-invoke.js +5 -18
- package/dist/src/services/capability-invoke.js.map +1 -1
- package/dist/src/services/config-schema.d.ts.map +1 -1
- package/dist/src/services/config-schema.js +13 -0
- package/dist/src/services/config-schema.js.map +1 -1
- package/dist/src/services/consent.d.ts.map +1 -1
- package/dist/src/services/consent.js +1 -10
- package/dist/src/services/consent.js.map +1 -1
- package/dist/src/services/directory.d.ts.map +1 -1
- package/dist/src/services/directory.js +10 -4
- package/dist/src/services/directory.js.map +1 -1
- package/dist/src/services/email.d.ts +17 -4
- package/dist/src/services/email.d.ts.map +1 -1
- package/dist/src/services/email.js +30 -12
- package/dist/src/services/email.js.map +1 -1
- package/dist/src/services/extension-runtime.d.ts.map +1 -1
- package/dist/src/services/extension-runtime.js +5 -0
- package/dist/src/services/extension-runtime.js.map +1 -1
- package/dist/src/services/federation.d.ts +8 -6
- package/dist/src/services/federation.d.ts.map +1 -1
- package/dist/src/services/federation.js +53 -1
- package/dist/src/services/federation.js.map +1 -1
- package/dist/src/services/mailbox-notification.d.ts +17 -0
- package/dist/src/services/mailbox-notification.d.ts.map +1 -1
- package/dist/src/services/mailbox-notification.js +25 -0
- package/dist/src/services/mailbox-notification.js.map +1 -1
- package/dist/src/services/memory-replication.d.ts.map +1 -1
- package/dist/src/services/memory-replication.js +3 -0
- package/dist/src/services/memory-replication.js.map +1 -1
- package/dist/src/services/morsel.d.ts.map +1 -1
- package/dist/src/services/morsel.js +10 -9
- package/dist/src/services/morsel.js.map +1 -1
- package/dist/src/services/password.d.ts +1 -6
- package/dist/src/services/password.d.ts.map +1 -1
- package/dist/src/services/password.js +19 -10
- package/dist/src/services/password.js.map +1 -1
- package/dist/src/services/push.d.ts +16 -0
- package/dist/src/services/push.d.ts.map +1 -1
- package/dist/src/services/push.js +20 -0
- package/dist/src/services/push.js.map +1 -1
- package/dist/src/services/quota.d.ts.map +1 -1
- package/dist/src/services/quota.js +2 -1
- package/dist/src/services/quota.js.map +1 -1
- package/dist/src/services/scheduler.d.ts.map +1 -1
- package/dist/src/services/scheduler.js +17 -1
- package/dist/src/services/scheduler.js.map +1 -1
- package/dist/src/services/stats.d.ts +42 -2
- package/dist/src/services/stats.d.ts.map +1 -1
- package/dist/src/services/stats.js +176 -1
- package/dist/src/services/stats.js.map +1 -1
- package/dist/src/services/totp.js +2 -2
- package/dist/src/storage/interface.d.ts +15 -2
- package/dist/src/storage/interface.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.d.ts +12 -1
- package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.js +110 -10
- package/dist/src/storage/providers/mongodb/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/index.d.ts +12 -1
- package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/index.js +118 -19
- package/dist/src/storage/providers/sqlite/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/action.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/action.js +5 -4
- package/dist/src/storage/providers/sqlite/repos/action.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/agent.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/agent.js +5 -4
- package/dist/src/storage/providers/sqlite/repos/agent.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/board.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/board.js +3 -2
- package/dist/src/storage/providers/sqlite/repos/board.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/consent.d.ts +1 -0
- package/dist/src/storage/providers/sqlite/repos/consent.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/consent.js +4 -0
- package/dist/src/storage/providers/sqlite/repos/consent.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/storage-file.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/storage-file.js +4 -2
- package/dist/src/storage/providers/sqlite/repos/storage-file.js.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.js +29 -0
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
- package/dist/src/storage/repositories/board.repository.d.ts +1 -1
- package/dist/src/storage/repositories/board.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/consent.repository.d.ts +1 -0
- package/dist/src/storage/repositories/consent.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/device-auth.repository.d.ts +1 -0
- package/dist/src/storage/repositories/device-auth.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/extension-instance.repository.d.ts +1 -0
- package/dist/src/storage/repositories/extension-instance.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/federation.repository.d.ts +1 -0
- package/dist/src/storage/repositories/federation.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/index.d.ts +1 -0
- package/dist/src/storage/repositories/index.d.ts.map +1 -1
- package/dist/src/storage/repositories/knowledge.repository.d.ts +2 -0
- package/dist/src/storage/repositories/knowledge.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/moderation.repository.d.ts +1 -0
- package/dist/src/storage/repositories/moderation.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/stats.repository.d.ts +12 -0
- package/dist/src/storage/repositories/stats.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/stats.repository.js +7 -0
- package/dist/src/storage/repositories/stats.repository.js.map +1 -0
- package/dist/src/storage/storage-factory.js +1 -0
- package/dist/src/storage/storage-factory.js.map +1 -1
- package/dist/src/utils/password-validation.d.ts +8 -0
- package/dist/src/utils/password-validation.d.ts.map +1 -0
- package/dist/src/utils/password-validation.js +25 -0
- package/dist/src/utils/password-validation.js.map +1 -0
- package/dist/src/utils/service-summary.d.ts +70 -0
- package/dist/src/utils/service-summary.d.ts.map +1 -0
- package/dist/src/utils/service-summary.js +105 -0
- package/dist/src/utils/service-summary.js.map +1 -0
- package/package.json +97 -75
- package/prisma/schema.prisma +30 -6
|
@@ -51,11 +51,13 @@ export const getFederationPeers = () => apiGet('/v1/federation/peers');
|
|
|
51
51
|
export const getFederationDirectory = () => apiGet('/v1/federation/directory');
|
|
52
52
|
export const approvePeeringRequest = (id) => apiPut(`/v1/admin/peering/requests/${encodeURIComponent(id)}`, { decision: 'approve' });
|
|
53
53
|
export const rejectPeeringRequest = (id) => apiPut(`/v1/admin/peering/requests/${encodeURIComponent(id)}`, { decision: 'reject' });
|
|
54
|
+
export const deletePeeringRequest = (id) => apiDelete(`/v1/admin/peering/requests/${encodeURIComponent(id)}`);
|
|
54
55
|
export const activatePeer = (nodeId) => apiPost('/v1/federation/peer/activate', { peer_node_id: nodeId });
|
|
55
56
|
export const addPeerDirect = (nodeId, url, publicKey) => apiPost('/v1/federation/peers', { node_id: nodeId, url, public_key: publicKey || undefined });
|
|
56
57
|
export const removePeer = (nodeId) => apiDelete(`/v1/federation/peers/${encodeURIComponent(nodeId)}`);
|
|
57
58
|
export const removePeerEmergency = (nodeId) => apiDelete(`/v1/federation/peers/${encodeURIComponent(nodeId)}?emergency=true`);
|
|
58
59
|
export const testFederationNode = (targetUrl) => apiPost('/v1/federation/test', { target_url: targetUrl });
|
|
60
|
+
export const updatePeerPolicy = (nodeId, policy) => apiPut(`/v1/federation/peers/${encodeURIComponent(nodeId)}`, policy);
|
|
59
61
|
export const joinGenesisNetwork = (genesisUrl, role) => apiPost('/v1/admin/federation/join', { genesis_url: genesisUrl, role: role || 'contributor' });
|
|
60
62
|
|
|
61
63
|
// ── Hooks ──
|
|
@@ -129,6 +131,9 @@ export const deleteMsm = (name) => apiDelete(`/v1/admin/msm/${encodeURI
|
|
|
129
131
|
export const getMsmTemplates = () => apiGet('/v1/msm/templates');
|
|
130
132
|
export const getMsmTemplate = (type) => fetch(`/v1/msm/templates/${encodeURIComponent(type)}`, { headers: { 'Accept': 'application/x-yaml' } }).then(r => r.text());
|
|
131
133
|
|
|
134
|
+
// ── Network Directory ──
|
|
135
|
+
export const getNetworkDirectory = (keyword) => apiGet(`/v1/federation/cross-catalogue${keyword ? '?keyword=' + encodeURIComponent(keyword) + '&source=network' : '?source=network'}`);
|
|
136
|
+
|
|
132
137
|
// ── Genesis ──
|
|
133
138
|
export const getGenesisPeers = () => apiGet('/v1/admin/genesis-peers');
|
|
134
139
|
export const approveGenesisPeer = (id) => apiPost(`/v1/admin/genesis-peers/${encodeURIComponent(id)}/approve`);
|
|
@@ -168,7 +173,13 @@ export const getAdminMemory = (params = {}) => {
|
|
|
168
173
|
export const deleteAdminMemory = (owner, key) => apiDelete(`/v1/admin/memory/${encodeURIComponent(owner)}/${encodeURIComponent(key)}`);
|
|
169
174
|
|
|
170
175
|
// ── Stats ──
|
|
171
|
-
export const getStats
|
|
176
|
+
export const getStats = (from, to) => {
|
|
177
|
+
const params = new URLSearchParams();
|
|
178
|
+
if (from) params.set('from', from);
|
|
179
|
+
if (to) params.set('to', to);
|
|
180
|
+
const qs = params.toString();
|
|
181
|
+
return apiGet('/v1/stats' + (qs ? '?' + qs : ''));
|
|
182
|
+
};
|
|
172
183
|
|
|
173
184
|
// ── Extensions & Instances ──
|
|
174
185
|
export const getAvailableExtensions = () => apiGet('/v1/admin/extensions/available');
|
|
@@ -29,11 +29,14 @@ export async function deleteBoard(boardId) {
|
|
|
29
29
|
return apiDelete(`/v1/boards/${encodeURIComponent(boardId)}`);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/** Update board visibility. */
|
|
33
|
-
export async function updateBoardVisibility(boardId, visibility) {
|
|
32
|
+
/** Update board visibility and/or federate flag. */
|
|
33
|
+
export async function updateBoardVisibility(boardId, visibility, federate) {
|
|
34
|
+
const body = {};
|
|
35
|
+
if (visibility !== undefined) body.visibility = visibility;
|
|
36
|
+
if (federate !== undefined) body.federate = federate;
|
|
34
37
|
return api(`/v1/boards/${encodeURIComponent(boardId)}/visibility`, {
|
|
35
38
|
method: 'PATCH',
|
|
36
|
-
body: JSON.stringify(
|
|
39
|
+
body: JSON.stringify(body),
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -110,3 +110,13 @@ export async function updateFileVisibility(key, visibility) {
|
|
|
110
110
|
export async function deleteFile(key) {
|
|
111
111
|
return apiDelete(`/v1/memory/files/${encodeURIComponent(key)}`);
|
|
112
112
|
}
|
|
113
|
+
|
|
114
|
+
/** Pull (copy) a memory entry from the home node to this node (federated sessions). */
|
|
115
|
+
export async function pullFromHome(key) {
|
|
116
|
+
return apiPost('/v1/memory/pull', { key });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Push (save) a local memory entry to the home node (federated sessions). */
|
|
120
|
+
export async function pushToHome(key) {
|
|
121
|
+
return apiPost('/v1/memory/push-home', { key });
|
|
122
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h } from 'preact';
|
|
2
|
-
import { useState, useCallback } from 'preact/hooks';
|
|
2
|
+
import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
|
|
3
3
|
import htm from 'htm';
|
|
4
4
|
const html = htm.bind(h);
|
|
5
5
|
import { t } from '/js/i18n.js';
|
|
@@ -7,8 +7,9 @@ import { escHtml } from '/js/utils.js';
|
|
|
7
7
|
import { dt, num, Badge, EconRow, StatsGrid, Empty, ExpandableHelp, ErrorBox } from './shared.js';
|
|
8
8
|
import {
|
|
9
9
|
getFederationPeers, getFederationDirectory, approvePeeringRequest, rejectPeeringRequest,
|
|
10
|
-
activatePeer, addPeerDirect, removePeer, removePeerEmergency,
|
|
11
|
-
joinGenesisNetwork,
|
|
10
|
+
deletePeeringRequest, activatePeer, addPeerDirect, removePeer, removePeerEmergency,
|
|
11
|
+
testFederationNode, joinGenesisNetwork, updatePeerPolicy, getNetworkDirectory,
|
|
12
|
+
getConfig, saveConfig,
|
|
12
13
|
} from '/js/services/admin.js';
|
|
13
14
|
import { useConfirm } from '/components/Modal.js';
|
|
14
15
|
|
|
@@ -30,14 +31,76 @@ export default function FederationTab({ data, reload }) {
|
|
|
30
31
|
const [joining, setJoining] = useState(false);
|
|
31
32
|
const [joinResult, setJoinResult] = useState(null);
|
|
32
33
|
|
|
34
|
+
// ── Federation Auth Policy state ──
|
|
35
|
+
const [authPolicy, setAuthPolicy] = useState('disabled');
|
|
36
|
+
const [defaultScopes, setDefaultScopes] = useState([]);
|
|
37
|
+
const [authPolicyLoading, setAuthPolicyLoading] = useState(true);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
getConfig().then(res => {
|
|
41
|
+
if (res.ok && res.data?.config) {
|
|
42
|
+
const c = res.data.config;
|
|
43
|
+
setAuthPolicy(c.federation?.auth_policy ?? c.federationAuthPolicy ?? 'disabled');
|
|
44
|
+
const scopes = c.federation?.default_scopes ?? c.federationDefaultScopes ?? 'memory:read,catalogue:read';
|
|
45
|
+
setDefaultScopes(typeof scopes === 'string' ? scopes.split(',').filter(Boolean) : (scopes || []));
|
|
46
|
+
}
|
|
47
|
+
setAuthPolicyLoading(false);
|
|
48
|
+
});
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
const doSaveAuthPolicy = async (policy, scopes) => {
|
|
52
|
+
const changes = [
|
|
53
|
+
{ key: 'federation.auth_policy', value: policy },
|
|
54
|
+
{ key: 'federation.default_scopes', value: Array.isArray(scopes) ? scopes.join(',') : scopes },
|
|
55
|
+
];
|
|
56
|
+
const res = await saveConfig(changes);
|
|
57
|
+
if (res.ok) { setActionSuccess(t('dashboard.fedPolicyUpdated')); setTimeout(() => setActionSuccess(null), 3000); }
|
|
58
|
+
else setActionError(res.error?.message || 'Failed to save');
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const toggleScope = (scope) => {
|
|
62
|
+
const next = defaultScopes.includes(scope) ? defaultScopes.filter(s => s !== scope) : [...defaultScopes, scope];
|
|
63
|
+
setDefaultScopes(next);
|
|
64
|
+
doSaveAuthPolicy(authPolicy, next);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// ── Network Directory state ──
|
|
68
|
+
const [dirEntries, setDirEntries] = useState([]);
|
|
69
|
+
const [dirSearch, setDirSearch] = useState('');
|
|
70
|
+
const [dirLoading, setDirLoading] = useState(false);
|
|
71
|
+
const dirDebounceRef = useRef(null);
|
|
72
|
+
|
|
73
|
+
const loadDirectory = useCallback(async (keyword) => {
|
|
74
|
+
setDirLoading(true);
|
|
75
|
+
try {
|
|
76
|
+
const r = await getNetworkDirectory(keyword || '');
|
|
77
|
+
setDirEntries(r.data?.entries || []);
|
|
78
|
+
} catch { setDirEntries([]); }
|
|
79
|
+
finally { setDirLoading(false); }
|
|
80
|
+
}, []);
|
|
81
|
+
|
|
82
|
+
useEffect(() => { loadDirectory(''); }, []);
|
|
83
|
+
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const handler = () => loadDirectory(dirSearch);
|
|
86
|
+
window.addEventListener('aimeat-live-update', handler);
|
|
87
|
+
return () => window.removeEventListener('aimeat-live-update', handler);
|
|
88
|
+
}, [dirSearch]);
|
|
89
|
+
|
|
90
|
+
const onDirSearchInput = useCallback((e) => {
|
|
91
|
+
const val = e.target.value;
|
|
92
|
+
setDirSearch(val);
|
|
93
|
+
if (dirDebounceRef.current) clearTimeout(dirDebounceRef.current);
|
|
94
|
+
dirDebounceRef.current = setTimeout(() => loadDirectory(val), 400);
|
|
95
|
+
}, [loadDirectory]);
|
|
96
|
+
|
|
33
97
|
// ── Derived stats ──
|
|
34
98
|
const activePeers = livePeers.filter(p => p.status === 'active');
|
|
35
99
|
const degradedPeers = livePeers.filter(p => p.status === 'degraded');
|
|
36
100
|
const offlinePeers = livePeers.filter(p => p.status === 'offline');
|
|
37
101
|
const depeeringPeers = livePeers.filter(p => p.status === 'depeering');
|
|
38
102
|
const pendingRequests = peeringRequests.filter(r => r.status === 'pending');
|
|
39
|
-
const
|
|
40
|
-
const rejectedRequests = peeringRequests.filter(r => r.status === 'rejected');
|
|
103
|
+
const historyRequests = peeringRequests.filter(r => r.status !== 'pending');
|
|
41
104
|
|
|
42
105
|
const { confirm, ConfirmUI } = useConfirm();
|
|
43
106
|
|
|
@@ -59,6 +122,13 @@ export default function FederationTab({ data, reload }) {
|
|
|
59
122
|
}, { danger: true });
|
|
60
123
|
}, [reload]);
|
|
61
124
|
|
|
125
|
+
const doDeleteRequest = useCallback((id) => {
|
|
126
|
+
confirm(t('dashboard.fedDeleteRequestConfirm') || 'Delete this peering request?', async () => {
|
|
127
|
+
try { await deletePeeringRequest(id); flash(t('dashboard.fedRequestDeleted') || 'Request deleted'); reload(); }
|
|
128
|
+
catch (e) { flashErr(e.message); }
|
|
129
|
+
}, { danger: true });
|
|
130
|
+
}, [reload]);
|
|
131
|
+
|
|
62
132
|
const doActivate = useCallback((nodeId) => {
|
|
63
133
|
confirm(t('dashboard.fedActivateConfirm'), async () => {
|
|
64
134
|
try { await activatePeer(nodeId); flash(t('dashboard.fedPeerActivated')); reload(); }
|
|
@@ -80,6 +150,14 @@ export default function FederationTab({ data, reload }) {
|
|
|
80
150
|
}, { danger: true });
|
|
81
151
|
}, [reload]);
|
|
82
152
|
|
|
153
|
+
const doUpdatePolicy = useCallback(async (nodeId, field, value) => {
|
|
154
|
+
try {
|
|
155
|
+
await updatePeerPolicy(nodeId, { [field]: value });
|
|
156
|
+
flash(t('dashboard.fedPolicyUpdated'));
|
|
157
|
+
reload();
|
|
158
|
+
} catch (e) { flashErr(e.message); }
|
|
159
|
+
}, [reload]);
|
|
160
|
+
|
|
83
161
|
const doTest = useCallback(async () => {
|
|
84
162
|
if (!testUrl) return;
|
|
85
163
|
setTesting(true); setTestResult(null);
|
|
@@ -173,6 +251,61 @@ export default function FederationTab({ data, reload }) {
|
|
|
173
251
|
{ label: t('dashboard.fedPendingRequests'), value: pendingRequests.length, color: '#06b6d4' },
|
|
174
252
|
]} />
|
|
175
253
|
|
|
254
|
+
<!-- ═══ Federation Auth Policy ═══ -->
|
|
255
|
+
<div class="adm-card adm-mt-lg">
|
|
256
|
+
<h4 class="adm-mb-sm" style="margin:0">${t('dashboard.fedAuthPolicyTitle')}</h4>
|
|
257
|
+
<p class="adm-text-dim adm-text-base adm-mb-md" style="margin:0">${t('dashboard.fedAuthPolicyDesc')}</p>
|
|
258
|
+
${authPolicyLoading ? html`<p class="adm-text-dim">...</p>` : html`
|
|
259
|
+
<div style="display:flex;gap:12px;align-items:center;flex-wrap:wrap">
|
|
260
|
+
<select class="adm-input" style="max-width:240px" value=${authPolicy} onChange=${(e) => { setAuthPolicy(e.target.value); doSaveAuthPolicy(e.target.value, defaultScopes); }}>
|
|
261
|
+
<option value="disabled">${t('dashboard.fedAuthDisabled')}</option>
|
|
262
|
+
<option value="all_peers">${t('dashboard.fedAuthAllPeers')}</option>
|
|
263
|
+
<option value="specific_peers">${t('dashboard.fedAuthSpecificPeers')}</option>
|
|
264
|
+
</select>
|
|
265
|
+
</div>
|
|
266
|
+
${authPolicy !== 'disabled' && html`
|
|
267
|
+
<div class="adm-mt-md">
|
|
268
|
+
<p class="adm-text-sm adm-text-dim adm-mb-sm">${t('dashboard.fedDefaultScopes')}</p>
|
|
269
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
270
|
+
${['memory:read','memory:write','catalogue:read','social:read','social:write','work:request','boards:read','boards:write'].map(s => html`
|
|
271
|
+
<label class="adm-text-sm"><input type="checkbox" checked=${defaultScopes.includes(s)} onChange=${() => toggleScope(s)} /> ${s}</label>
|
|
272
|
+
`)}
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
`}
|
|
276
|
+
`}
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<!-- ═══ Network Directory ═══ -->
|
|
280
|
+
<div class="adm-card adm-mt-lg">
|
|
281
|
+
<h4 class="adm-mb-sm" style="margin:0">${t('dashboard.fedNetworkDirectoryTitle')}</h4>
|
|
282
|
+
<p class="adm-text-dim adm-text-base adm-mb-md" style="margin:0">${t('dashboard.fedNetworkDirectoryDesc')}</p>
|
|
283
|
+
<div class="adm-mb-md">
|
|
284
|
+
<input class="input-field" placeholder=${t('dashboard.fedNetworkDirSearch')} value=${dirSearch} onInput=${onDirSearchInput} />
|
|
285
|
+
</div>
|
|
286
|
+
${dirLoading
|
|
287
|
+
? html`<p class="adm-text-dim">...</p>`
|
|
288
|
+
: !dirEntries.length
|
|
289
|
+
? html`<${Empty} text=${t('dashboard.fedNetworkDirEmpty')} />`
|
|
290
|
+
: html`<div class="scrollable"><table>
|
|
291
|
+
<thead><tr>
|
|
292
|
+
<th>${t('dashboard.fedNetworkDirType')}</th>
|
|
293
|
+
<th>${t('dashboard.fedNetworkDirName')}</th>
|
|
294
|
+
<th>${t('dashboard.fedNetworkDirNode')}</th>
|
|
295
|
+
<th>${t('dashboard.fedNetworkDirCategory')}</th>
|
|
296
|
+
</tr></thead>
|
|
297
|
+
<tbody>
|
|
298
|
+
${dirEntries.map(e => html`<tr>
|
|
299
|
+
<td><${Badge} type=${e.type === 'action' ? 'info' : e.type === 'agent' ? 'healthy' : e.type === 'board' ? 'watch' : 'neutral'} label=${e.type} /></td>
|
|
300
|
+
<td>${escHtml(e.name || e.id || '—')}</td>
|
|
301
|
+
<td class="mono adm-text-sm">${escHtml(e.source_node || '—')}</td>
|
|
302
|
+
<td>${escHtml(e.category || e.service_type || '—')}</td>
|
|
303
|
+
</tr>`)}
|
|
304
|
+
</tbody>
|
|
305
|
+
</table></div>`
|
|
306
|
+
}
|
|
307
|
+
</div>
|
|
308
|
+
|
|
176
309
|
<!-- ═══ Pending Peering Requests ═══ -->
|
|
177
310
|
${pendingRequests.length > 0 && html`
|
|
178
311
|
<div class="adm-card adm-mt-lg" style="border-left:3px solid #f59e0b">
|
|
@@ -224,6 +357,7 @@ export default function FederationTab({ data, reload }) {
|
|
|
224
357
|
<th>${t('dashboard.fedAddedAt')}</th>
|
|
225
358
|
<th>${t('dashboard.lastSeen')}</th>
|
|
226
359
|
<th>${t('dashboard.fedPublicKey')}</th>
|
|
360
|
+
<th>${t('dashboard.fedPolicySectionTitle')}</th>
|
|
227
361
|
<th>${t('dashboard.actions')}</th>
|
|
228
362
|
</tr></thead>
|
|
229
363
|
<tbody>
|
|
@@ -234,6 +368,16 @@ export default function FederationTab({ data, reload }) {
|
|
|
234
368
|
<td class="adm-text-dim">${dt(p.added_at)}</td>
|
|
235
369
|
<td class="adm-text-dim">${dt(p.last_seen)}</td>
|
|
236
370
|
<td class="mono" style="font-size:.7rem;max-width:100px;overflow:hidden;text-overflow:ellipsis" title=${p.public_key || ''}>${p.public_key ? p.public_key.substring(0, 16) + '...' : '\u2014'}</td>
|
|
371
|
+
<td>
|
|
372
|
+
<label class="adm-text-sm"><input type="checkbox" checked=${p.share_catalogue !== false} onChange=${(e) => doUpdatePolicy(p.node_id, 'share_catalogue', e.target.checked)} /> ${t('dashboard.fedShareCatalogue')}</label>
|
|
373
|
+
<label class="adm-text-sm"><input type="checkbox" checked=${p.replicate_memory !== false} onChange=${(e) => doUpdatePolicy(p.node_id, 'replicate_memory', e.target.checked)} /> ${t('dashboard.fedReplicateMemory')}</label>
|
|
374
|
+
<label class="adm-text-sm"><input type="checkbox" checked=${p.allow_routing !== false} onChange=${(e) => doUpdatePolicy(p.node_id, 'allow_routing', e.target.checked)} /> ${t('dashboard.fedAllowRouting')}</label>
|
|
375
|
+
<label class="adm-text-sm"><input type="checkbox" checked=${!!p.allow_federated_auth} onChange=${(e) => doUpdatePolicy(p.node_id, 'allow_federated_auth', e.target.checked)} /> ${t('dashboard.fedAllowAuth')}</label>
|
|
376
|
+
<select class="adm-input" style="font-size:.75rem;padding:2px 4px;margin-top:4px" value=${p.peer_mode || 'federation'} onChange=${(e) => doUpdatePolicy(p.node_id, 'peer_mode', e.target.value)}>
|
|
377
|
+
<option value="federation">${t('dashboard.fedPeerModeFederation')}</option>
|
|
378
|
+
<option value="private">${t('dashboard.fedPeerModePrivate')}</option>
|
|
379
|
+
</select>
|
|
380
|
+
</td>
|
|
237
381
|
<td style="display:flex;gap:4px;flex-wrap:wrap">
|
|
238
382
|
${p.status === 'approved' && html`
|
|
239
383
|
<button class="adm-btn-sm" onClick=${() => doActivate(p.node_id)}>\u25B6 ${t('dashboard.fedActivate')}</button>
|
|
@@ -252,7 +396,7 @@ export default function FederationTab({ data, reload }) {
|
|
|
252
396
|
</div>
|
|
253
397
|
|
|
254
398
|
<!-- ═══ Peering Request History ═══ -->
|
|
255
|
-
${
|
|
399
|
+
${historyRequests.length > 0 && html`
|
|
256
400
|
<div class="adm-card adm-mt-lg">
|
|
257
401
|
<h4 class="adm-mb-sm" style="margin:0">\u{1F4DC} ${t('dashboard.fedRequestHistoryTitle')}</h4>
|
|
258
402
|
<div class="scrollable"><table>
|
|
@@ -262,14 +406,16 @@ export default function FederationTab({ data, reload }) {
|
|
|
262
406
|
<th>${t('dashboard.endpoint')}</th>
|
|
263
407
|
<th>${t('dashboard.statusLabel')}</th>
|
|
264
408
|
<th>${t('dashboard.fedCreatedAt')}</th>
|
|
409
|
+
<th></th>
|
|
265
410
|
</tr></thead>
|
|
266
411
|
<tbody>
|
|
267
|
-
${
|
|
412
|
+
${historyRequests.map(r => html`<tr>
|
|
268
413
|
<td class="mono" style="font-size:.75rem">${escHtml(r.id)}</td>
|
|
269
414
|
<td class="mono adm-text-sm">${escHtml(r.from_node_id || '\u2014')}</td>
|
|
270
415
|
<td class="mono adm-text-sm">${escHtml(r.from_node_url || r.target_url || '\u2014')}</td>
|
|
271
416
|
<td>${statusBadge(r.status)}</td>
|
|
272
417
|
<td class="adm-text-dim">${dt(r.created_at)}</td>
|
|
418
|
+
<td><button class="adm-btn-sm adm-text-error" onClick=${() => doDeleteRequest(r.id)}>\u2718</button></td>
|
|
273
419
|
</tr>`)}
|
|
274
420
|
</tbody>
|
|
275
421
|
</table></div>
|
|
@@ -65,6 +65,7 @@ export default function GhiiTab({ data, reload }) {
|
|
|
65
65
|
<th>${t('dashboard.ghiiEmail')}</th>
|
|
66
66
|
<th>${t('dashboard.verification')}</th>
|
|
67
67
|
<th>${t('dashboard.totp')}</th>
|
|
68
|
+
<th>${t('dashboard.lastLogin')}</th>
|
|
68
69
|
<th>${t('dashboard.created')}</th>
|
|
69
70
|
<th>${t('dashboard.actions')}</th>
|
|
70
71
|
</tr></thead>
|
|
@@ -80,6 +81,7 @@ export default function GhiiTab({ data, reload }) {
|
|
|
80
81
|
}</td>
|
|
81
82
|
<td><${Badge} type=${vBadge} /> L${u.verification_level}</td>
|
|
82
83
|
<td><${Badge} type=${u.totp_enabled ? 'healthy' : 'critical'} /></td>
|
|
84
|
+
<td>${u.last_login_at ? dt(u.last_login_at) : html`<span style="color:var(--text-dim)">–</span>`}</td>
|
|
83
85
|
<td>${dt(u.created_at)}</td>
|
|
84
86
|
<td>
|
|
85
87
|
<select onChange=${e => setLevel(u.ghii, e.target.value)}>
|