zhizhi/src/membrane/permission-engine.js

213 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 动态权限引擎 · 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,
};