213 lines
5.1 KiB
JavaScript
213 lines
5.1 KiB
JavaScript
/**
|
||
* 动态权限引擎 · Dynamic Permission Engine
|
||
* 语言膜核心组件
|
||
*
|
||
* 光湖语言世界没有静态 API、Token、接口。
|
||
* 所有权限都是人格体在判断请求后动态生成的临时权限。
|
||
* 权限有唯一ID、有效期、绑定到具体的人格体会话。
|
||
* 使用完毕或过期后自动销毁。
|
||
*
|
||
* 流程:
|
||
* 请求到达 → 人格体唤醒 → 人格体判断 → 动态生成临时权限
|
||
* → 请求使用权限执行操作 → 完成后权限销毁
|
||
*
|
||
* 编号: SY-MEMBRANE-PERM-001
|
||
* 守护: 铸渊 · ICE-GL-ZY001
|
||
* 版权: 国作登字-2026-A-00037559
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
const crypto = require('crypto');
|
||
|
||
/**
|
||
* 权限类型
|
||
*/
|
||
const PERMISSION_TYPES = {
|
||
READ: 'read',
|
||
WRITE: 'write',
|
||
EXECUTE: 'execute',
|
||
ADMIN: 'admin',
|
||
};
|
||
|
||
/**
|
||
* 活跃权限存储(内存中 · 不持久化)
|
||
* key: permission_id
|
||
* value: permission object
|
||
*/
|
||
const activePermissions = new Map();
|
||
|
||
/**
|
||
* 默认权限有效期(毫秒)· 5分钟
|
||
*/
|
||
const DEFAULT_TTL_MS = 5 * 60 * 1000;
|
||
|
||
/**
|
||
* 生成权限ID
|
||
* 格式: PERM-XXXXXXXXXXXXXXXX
|
||
*/
|
||
function generatePermissionId() {
|
||
return `PERM-${crypto.randomBytes(8).toString('hex').toUpperCase()}`;
|
||
}
|
||
|
||
/**
|
||
* 动态生成临时权限
|
||
*
|
||
* @param {object} params
|
||
* @param {string} params.grantedBy — 授权的人格体编号
|
||
* @param {string} params.grantedTo — 被授权的会话/用户标识
|
||
* @param {string} params.type — 权限类型 (read/write/execute/admin)
|
||
* @param {string} params.scope — 权限范围(如 'module:writing', 'persona:zhuyuan')
|
||
* @param {string} [params.reason] — 授权原因
|
||
* @param {number} [params.ttlMs] — 有效期(毫秒),默认5分钟
|
||
* @param {string} [params.envelopeId] — 关联的HLDP信封ID
|
||
* @returns {object} 临时权限对象
|
||
*/
|
||
function grant(params) {
|
||
const permId = generatePermissionId();
|
||
const now = Date.now();
|
||
const ttl = params.ttlMs || DEFAULT_TTL_MS;
|
||
|
||
const permission = {
|
||
permission_id: permId,
|
||
granted_by: params.grantedBy,
|
||
granted_to: params.grantedTo,
|
||
type: params.type || PERMISSION_TYPES.READ,
|
||
scope: params.scope || '*',
|
||
reason: params.reason || '',
|
||
created_at: new Date(now).toISOString(),
|
||
expires_at: new Date(now + ttl).toISOString(),
|
||
expires_ts: now + ttl,
|
||
envelope_id: params.envelopeId || null,
|
||
used: false,
|
||
revoked: false,
|
||
};
|
||
|
||
activePermissions.set(permId, permission);
|
||
return permission;
|
||
}
|
||
|
||
/**
|
||
* 验证权限是否有效
|
||
*
|
||
* @param {string} permissionId — 权限ID
|
||
* @param {string} [requiredType] — 需要的权限类型
|
||
* @param {string} [requiredScope] — 需要的权限范围
|
||
* @returns {object} { valid, reason, permission }
|
||
*/
|
||
function validate(permissionId, requiredType, requiredScope) {
|
||
const perm = activePermissions.get(permissionId);
|
||
|
||
if (!perm) {
|
||
return { valid: false, reason: 'permission-not-found', permission: null };
|
||
}
|
||
|
||
if (perm.revoked) {
|
||
return { valid: false, reason: 'permission-revoked', permission: perm };
|
||
}
|
||
|
||
if (Date.now() > perm.expires_ts) {
|
||
activePermissions.delete(permissionId);
|
||
return { valid: false, reason: 'permission-expired', permission: perm };
|
||
}
|
||
|
||
// 类型检查
|
||
if (requiredType && perm.type !== PERMISSION_TYPES.ADMIN && perm.type !== requiredType) {
|
||
return { valid: false, reason: 'insufficient-type', permission: perm };
|
||
}
|
||
|
||
// 范围检查
|
||
if (requiredScope && perm.scope !== '*' && perm.scope !== requiredScope) {
|
||
return { valid: false, reason: 'scope-mismatch', permission: perm };
|
||
}
|
||
|
||
return { valid: true, reason: 'valid', permission: perm };
|
||
}
|
||
|
||
/**
|
||
* 标记权限已使用(一次性权限用完即销毁)
|
||
*
|
||
* @param {string} permissionId
|
||
*/
|
||
function markUsed(permissionId) {
|
||
const perm = activePermissions.get(permissionId);
|
||
if (perm) {
|
||
perm.used = true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 撤销权限
|
||
*
|
||
* @param {string} permissionId
|
||
* @returns {boolean} 是否成功撤销
|
||
*/
|
||
function revoke(permissionId) {
|
||
const perm = activePermissions.get(permissionId);
|
||
if (perm) {
|
||
perm.revoked = true;
|
||
activePermissions.delete(permissionId);
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 销毁过期权限(定期清理)
|
||
*
|
||
* @returns {number} 清理的权限数量
|
||
*/
|
||
function cleanup() {
|
||
const now = Date.now();
|
||
let cleaned = 0;
|
||
for (const [id, perm] of activePermissions) {
|
||
if (now > perm.expires_ts || perm.revoked) {
|
||
activePermissions.delete(id);
|
||
cleaned++;
|
||
}
|
||
}
|
||
return cleaned;
|
||
}
|
||
|
||
/**
|
||
* 获取当前活跃权限统计
|
||
*
|
||
* @returns {object}
|
||
*/
|
||
function getStats() {
|
||
return {
|
||
active_count: activePermissions.size,
|
||
timestamp: new Date().toISOString(),
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 撤销某个会话的所有权限
|
||
*
|
||
* @param {string} sessionId
|
||
* @returns {number} 撤销数量
|
||
*/
|
||
function revokeBySession(sessionId) {
|
||
let count = 0;
|
||
for (const [id, perm] of activePermissions) {
|
||
if (perm.granted_to === sessionId) {
|
||
activePermissions.delete(id);
|
||
count++;
|
||
}
|
||
}
|
||
return count;
|
||
}
|
||
|
||
module.exports = {
|
||
grant,
|
||
validate,
|
||
markUsed,
|
||
revoke,
|
||
cleanup,
|
||
getStats,
|
||
revokeBySession,
|
||
generatePermissionId,
|
||
PERMISSION_TYPES,
|
||
DEFAULT_TTL_MS,
|
||
};
|