2026-07-24 10:39:10 +08:00
"use strict" ;
const crypto = require ( "node:crypto" ) ;
const fs = require ( "node:fs" ) ;
const http = require ( "node:http" ) ;
const path = require ( "node:path" ) ;
const { WorkOrderManager } = require ( "./workorder-manager" ) ;
const { MapGate } = require ( "./map-gate" ) ;
const { sendSmtpMail } = require ( "./smtp-mailer" ) ;
const { executeRegisteredAction } = require ( "./action-client" ) ;
const DEFAULT _ACTIONS = Object . freeze ( {
2026-07-26 14:23:47 +08:00
"server-login" : [
"read-navigation-map" ,
"inspect-services" ,
"health-check" ,
"inspect-code-channel-owner-auth" ,
] ,
2026-07-24 10:39:10 +08:00
"server-ops" : [
"read-navigation-map" ,
"inspect-services" ,
"pull-registered-repo" ,
"deploy-registered-service" ,
"restart-registered-service" ,
"health-check" ,
"rollback-registered-service" ,
"provision-approved-architecture" ,
"push-repository" ,
"restore-owner-password-login" ,
2026-07-26 15:02:01 +08:00
"restore-code-channel-owner-login" ,
2026-07-24 10:39:10 +08:00
] ,
"repo-push" : [ "read-navigation-map" , "push-repository" ] ,
} ) ;
function createApp ( options = { } ) {
const requestToken = options . requestToken || process . env . LAKE _LAMP _REQUEST _TOKEN || "" ;
const ownerEmail = options . ownerEmail || process . env . LAKE _LAMP _OWNER _EMAIL || "" ;
const approvers = options . approvers || loadApprovers ( options . approversFile || process . env . LAKE _LAMP _APPROVERS _FILE || "" , ownerEmail ) ;
const publicBaseUrl = String ( options . publicBaseUrl || process . env . LAKE _LAMP _PUBLIC _URL || "" ) . replace ( /\/$/ , "" ) ;
const targets = new Set ( options . targets || splitCsv ( process . env . LAKE _LAMP _TARGETS || "JD-FD-PRIMARY,BS-GZ-006" ) ) ;
const actions = options . actions || DEFAULT _ACTIONS ;
const manager = options . manager || new WorkOrderManager ( {
approvalTtl : Number ( options . approvalTtl || process . env . LAKE _LAMP _APPROVAL _TTL || 3 * 60 * 60 ) ,
sessionTtl : Number ( options . sessionTtl || process . env . LAKE _LAMP _SESSION _TTL || 3 * 60 * 60 ) ,
maxSessionLifetime : Number ( options . maxSessionLifetime || process . env . LAKE _LAMP _MAX _SESSION _LIFETIME || 24 * 60 * 60 ) ,
stateFile : Object . prototype . hasOwnProperty . call ( options , "stateFile" ) ? options . stateFile : ( process . env . LAKE _LAMP _STATE _FILE || "/var/lib/guanghu/lake-lamp-authz/state.json" ) ,
} ) ;
const sendEmail = options . sendEmail || ( message => sendSmtpMail ( {
... message ,
smtpHost : process . env . SMTP _HOST || "smtp.qq.com" ,
smtpPort : Number ( process . env . SMTP _PORT || 465 ) ,
smtpUser : process . env . SMTP _USER || ownerEmail ,
smtpPass : process . env . QQ _SMTP _AUTH _CODE || "" ,
} ) ) ;
const mapGate = options . mapGate || new MapGate ( {
mapsDir : options . mapsDir || process . env . LAKE _LAMP _MAPS _DIR || "/etc/guanghu/navigation-maps" ,
stateFile : Object . prototype . hasOwnProperty . call ( options , "mapStateFile" ) ? options . mapStateFile : ( process . env . LAKE _LAMP _MAP _STATE _FILE || "/var/lib/guanghu/lake-lamp-authz/map-acks.json" ) ,
} ) ;
const repoGrantDir = options . repoGrantDir || process . env . LAKE _LAMP _REPO _GRANT _DIR || "/var/lib/guanghu/repo-authorizations" ;
const executeAction = options . executeAction || executeRegisteredAction ;
// Creating a powerless request must never become harder than the human mail
// handoff. Keep at least three attempts per network each hour.
const publicCreateLimit = Math . max ( 3 , Number ( options . publicCreateLimit || process . env . LAKE _LAMP _PUBLIC _CREATE _LIMIT || 24 ) ) ;
const publicCreateLimiter = options . publicCreateLimiter || new SlidingWindowLimiter ( publicCreateLimit , 60 * 60 ) ;
const publicCreateGlobalLimiter = options . publicCreateGlobalLimiter || new SlidingWindowLimiter ( Number ( options . publicCreateGlobalLimit || process . env . LAKE _LAMP _PUBLIC _CREATE _GLOBAL _LIMIT || 60 ) , 60 * 60 ) ;
// Owner handoff is a human recovery path, not a login endpoint. Always allow
// at least three genuine mail attempts per network each hour, even if an old
// deployment environment accidentally configures a lower value.
const publicMailLimit = Math . max ( 3 , Number ( options . publicMailLimit || process . env . LAKE _LAMP _PUBLIC _MAIL _LIMIT || 12 ) ) ;
const publicMailLimiter = options . publicMailLimiter || new SlidingWindowLimiter ( publicMailLimit , 60 * 60 ) ;
const publicMailGlobalLimiter = options . publicMailGlobalLimiter || new SlidingWindowLimiter ( Number ( options . publicMailGlobalLimit || process . env . LAKE _LAMP _PUBLIC _MAIL _GLOBAL _LIMIT || 30 ) , 60 * 60 ) ;
async function sendApprovalEmail ( handoffToken ) {
const issued = manager . issueApproval ( handoffToken ) ;
if ( ! issued . ok ) return issued ;
const approver = selectApprover ( approvers , issued . order ) ;
if ( ! approver ) {
manager . failApprovalEmail ( handoffToken ) ;
return { ok : false , reason : "no_registered_approver" } ;
}
const approvalUrl = ` ${ publicBaseUrl } /approve/ ${ issued . approvalToken } ` ;
const emailSent = await sendEmail ( {
to : approver . email ,
subject : ` 小湖灯授权请求 · ${ issued . order . target } ` ,
approvalUrl ,
order : issued . order ,
} ) ;
if ( ! emailSent ) {
manager . failApprovalEmail ( handoffToken ) ;
return { ok : false , reason : "authorization_email_failed" } ;
}
return { ok : true , order : issued . order } ;
}
return http . createServer ( async ( req , res ) => {
try {
const url = new URL ( req . url , "http://localhost" ) ;
if ( req . method === "GET" && url . pathname === "/health" ) return json ( res , 200 , {
ok : true ,
service : "lake-lamp-authz" ,
auth _mode : "email-link" ,
approval _ttl : manager . approvalTtl ,
session _ttl : manager . sessionTtl ,
max _session _lifetime : manager . maxSessionLifetime ,
auto _renew _on _activity : true ,
} ) ;
if ( req . method === "GET" && url . pathname === "/api/public/capabilities" ) return json ( res , 200 , {
schema : "guanghu.lake-lamp-public-workorder/v1" ,
create _workorder : ` ${ publicBaseUrl } /api/public/workorders ` ,
required _fields : [ "persona_id" , "target" , "scope" , "action" ] ,
optional _fields : [ "persona_name" , "description" , "resource" ] ,
targets : [ ... targets ] ,
scopes : actions ,
owner _handoff : "open request_url and request pre-registered mailbox verification" ,
approval _ttl : manager . approvalTtl ,
session _ttl : manager . sessionTtl ,
max _session _lifetime : manager . maxSessionLifetime ,
auto _renew _on _activity : true ,
limits : {
create _per _network _per _hour : publicCreateLimit ,
email _per _network _per _hour : publicMailLimit ,
} ,
} ) ;
const requestMatch = url . pathname . match ( /^\/request\/([A-Za-z0-9_-]{20,})$/ ) ;
if ( requestMatch && req . method === "GET" ) {
const inspected = manager . inspectHandoff ( requestMatch [ 1 ] ) ;
if ( ! inspected . ok ) return html ( res , 410 , requestErrorPage ( inspected . reason ) ) ;
return html ( res , 200 , requestPage ( inspected . order ) ) ;
}
if ( requestMatch && req . method === "POST" ) {
const inspected = manager . inspectHandoff ( requestMatch [ 1 ] ) ;
if ( ! inspected . ok ) return html ( res , 410 , requestErrorPage ( inspected . reason ) ) ;
// Refreshing or reopening an already-sent request must not consume a
// second rate-limit slot. It also must not send a duplicate email.
if ( inspected . order . approval _email _sent ) return html ( res , 200 , emailSentPage ( inspected . order ) ) ;
const source = clientAddress ( req ) ;
if ( ! publicMailLimiter . take ( source ) || ! publicMailGlobalLimiter . take ( "global" ) ) return html ( res , 429 , requestErrorPage ( "rate_limited" ) ) ;
const sent = await sendApprovalEmail ( requestMatch [ 1 ] ) ;
if ( ! sent . ok && sent . reason !== "approval_email_already_sent" ) return html ( res , sent . reason === "authorization_email_failed" ? 502 : 410 , requestErrorPage ( sent . reason ) ) ;
return html ( res , 200 , emailSentPage ( sent . order ) ) ;
}
const approvalMatch = url . pathname . match ( /^\/approve\/([A-Za-z0-9_-]{20,})$/ ) ;
if ( approvalMatch && req . method === "GET" ) {
const inspected = manager . inspectApproval ( approvalMatch [ 1 ] ) ;
if ( ! inspected . ok ) return html ( res , 410 , approvalErrorPage ( inspected . reason ) ) ;
return html ( res , 200 , approvalPage ( inspected . order , approvalMatch [ 1 ] ) ) ;
}
if ( approvalMatch && req . method === "POST" ) {
const approved = manager . approve ( approvalMatch [ 1 ] ) ;
if ( ! approved . ok ) return html ( res , 410 , approvalErrorPage ( approved . reason ) ) ;
return html ( res , 200 , approvedPage ( approved . order ) ) ;
}
if ( req . method === "POST" && url . pathname === "/api/public/workorders" ) {
const source = clientAddress ( req ) ;
if ( ! publicCreateLimiter . take ( source ) || ! publicCreateGlobalLimiter . take ( "global" ) ) return json ( res , 429 , { error : "rate_limited" , retry _after : 3600 } ) ;
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
const validation = validateWorkorderBody ( body , targets , actions ) ;
if ( ! validation . ok ) return json ( res , validation . status , { error : validation . error } ) ;
const created = manager . request ( validation . request ) ;
return json ( res , 201 , {
ok : true ,
workorder _id : created . id ,
claim _token : created . claimToken ,
request _url : ` ${ publicBaseUrl } /request/ ${ created . handoffToken } ` ,
expires _in : created . expiresIn ,
status : "waiting_for_owner_handoff" ,
} ) ;
}
if ( req . method === "POST" && url . pathname === "/api/workorders" ) {
if ( ! bearerMatches ( req , requestToken ) ) return json ( res , 401 , { error : "request_auth_required" } ) ;
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
const validation = validateWorkorderBody ( body , targets , actions ) ;
if ( ! validation . ok ) return json ( res , validation . status , { error : validation . error } ) ;
const expectedFingerprint = sha256 ( ownerEmail . toLowerCase ( ) ) ;
if ( ! body . recipient _fingerprint || ! safeEqual ( body . recipient _fingerprint , expectedFingerprint ) ) return json ( res , 403 , { error : "owner_identity_mismatch" } ) ;
const created = manager . request ( validation . request ) ;
const sent = await sendApprovalEmail ( created . handoffToken ) ;
if ( ! sent . ok ) return json ( res , 502 , { error : sent . reason } ) ;
return json ( res , 201 , { ok : true , workorder _id : created . id , claim _token : created . claimToken , expires _in : created . expiresIn , status : "waiting_for_owner" } ) ;
}
const claimMatch = url . pathname . match ( /^\/api\/workorders\/([0-9a-f-]{36})\/claim$/i ) ;
if ( req . method === "POST" && claimMatch ) {
const token = bearer ( req ) ;
const claimed = manager . claim ( claimMatch [ 1 ] , token ) ;
if ( ! claimed . ok ) return json ( res , claimed . reason === "approval_pending" ? 202 : 403 , { error : claimed . reason } ) ;
return json ( res , 200 , { ok : true , session _token : claimed . sessionToken , expires _in : claimed . expiresIn , target : claimed . target , scope : claimed . scope , action : claimed . action , resource : claimed . resource || "" } ) ;
}
if ( req . method === "POST" && url . pathname === "/api/session/verify" ) {
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
const verified = manager . verifySession ( bearer ( req ) , { pid : String ( body . persona _id || "" ) } , String ( body . target || "" ) , String ( body . scope || "" ) , String ( body . action || "" ) , Date . now ( ) / 1000 , Object . prototype . hasOwnProperty . call ( body , "resource" ) ? String ( body . resource || "" ) : undefined ) ;
if ( ! verified . ok ) return json ( res , 403 , { error : verified . reason } ) ;
if ( body . action !== "read-navigation-map" ) {
const map = mapGate . read ( String ( body . target || "" ) ) ;
const mapVerified = mapGate . verify ( bearer ( req ) , String ( body . target || "" ) , map . hash ) ;
if ( ! mapVerified . ok ) return json ( res , 423 , { error : mapVerified . reason , required _action : "read-navigation-map" } ) ;
}
return json ( res , 200 , { ok : true , expires _at : verified . session . expiresAt } ) ;
}
if ( req . method === "POST" && url . pathname === "/api/session/renew" ) {
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
if ( body . action || body . actions || body . target _override || body . scope _override || body . resource ) return json ( res , 400 , { error : "renewal_cannot_expand_authority" } ) ;
const token = bearer ( req ) ;
const target = String ( body . target || "" ) ;
const scope = String ( body . scope || "" ) ;
const renewed = manager . renewSession ( token , { pid : String ( body . persona _id || "" ) } , target , scope ) ;
if ( ! renewed . ok ) return json ( res , 403 , { error : renewed . reason } ) ;
const map = mapGate . read ( target ) ;
const acked = mapGate . ack ( token , target , map . hash , Date . now ( ) / 1000 , Math . max ( 1 , renewed . expiresAt - Date . now ( ) / 1000 ) ) ;
if ( ! acked . ok ) return json ( res , 409 , { error : acked . reason } ) ;
return json ( res , 200 , { ok : true , target , scope , expires _at : renewed . expiresAt , renewals : renewed . renewals , authority _expanded : false } ) ;
}
if ( req . method === "POST" && url . pathname === "/api/navigation-map/read" ) {
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
const verified = manager . verifySession ( bearer ( req ) , { pid : String ( body . persona _id || "" ) } , String ( body . target || "" ) , String ( body . scope || "" ) , "read-navigation-map" ) ;
if ( ! verified . ok ) return json ( res , 403 , { error : verified . reason } ) ;
const map = mapGate . read ( String ( body . target || "" ) ) ;
return json ( res , 200 , { ok : true , target : body . target , map _hash : map . hash , navigation _map : map . data } ) ;
}
if ( req . method === "POST" && url . pathname === "/api/navigation-map/ack" ) {
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
const token = bearer ( req ) ;
const verified = manager . verifySession ( token , { pid : String ( body . persona _id || "" ) } , String ( body . target || "" ) , String ( body . scope || "" ) , "read-navigation-map" ) ;
if ( ! verified . ok ) return json ( res , 403 , { error : verified . reason } ) ;
const acked = mapGate . ack ( token , String ( body . target || "" ) , String ( body . map _hash || "" ) , Date . now ( ) / 1000 , Math . max ( 1 , verified . session . expiresAt - Date . now ( ) / 1000 ) ) ;
return json ( res , acked . ok ? 200 : 409 , acked . ok ? { ok : true , target : body . target , map _hash : body . map _hash } : { error : acked . reason } ) ;
}
if ( req . method === "POST" && url . pathname === "/api/actions/execute" ) {
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
if ( body . cmd || body . command || body . shell || body . args ) return json ( res , 400 , { error : "arbitrary_command_forbidden" } ) ;
const token = bearer ( req ) ;
const target = String ( body . target || "" ) ;
const scope = String ( body . scope || "" ) ;
const action = String ( body . action || "" ) ;
const resource = String ( body . resource || "" ) ;
const verified = manager . verifySession ( token , { pid : String ( body . persona _id || "" ) } , target , scope , action , Date . now ( ) / 1000 , resource ) ;
if ( ! verified . ok ) return json ( res , 403 , { error : verified . reason } ) ;
const map = mapGate . read ( target ) ;
const mapVerified = mapGate . verify ( token , target , map . hash ) ;
if ( ! mapVerified . ok ) return json ( res , 423 , { error : mapVerified . reason , required _action : "read-navigation-map" } ) ;
const result = await executeAction ( resource ? { action , target , resource } : { action , target } ) ;
return json ( res , result . ok ? 200 : 502 , result ) ;
}
if ( req . method === "POST" && url . pathname === "/api/repo-push/grant" ) {
const body = await readJson ( req ) ;
if ( ! body ) return json ( res , 400 , { error : "invalid_json" } ) ;
const token = bearer ( req ) ;
const target = String ( body . target || "" ) ;
const scope = String ( body . scope || "repo-push" ) ;
const repo = String ( body . repo || "" ) . toLowerCase ( ) ;
if ( ! /^bingshuo\/[a-z0-9._-]+$/ . test ( repo ) ) return json ( res , 400 , { error : "repo_not_allowlisted" } ) ;
const verified = manager . verifySession ( token , { pid : String ( body . persona _id || "" ) } , target , scope , "push-repository" ) ;
if ( ! verified . ok ) return json ( res , 403 , { error : verified . reason } ) ;
const map = mapGate . read ( target ) ;
const mapVerified = mapGate . verify ( token , target , map . hash ) ;
if ( ! mapVerified . ok ) return json ( res , 423 , { error : mapVerified . reason , required _action : "read-navigation-map" } ) ;
fs . mkdirSync ( repoGrantDir , { recursive : true , mode : 0o2770 } ) ;
const grant = { schema : "guanghu.repo-push-grant/v1" , repo , target , persona _id : body . persona _id , map _hash : map . hash , issued _at : Date . now ( ) / 1000 , expires _at : verified . session . expiresAt } ;
const grantFile = path . join ( repoGrantDir , ` ${ repo . replace ( "/" , "__" ) } .json ` ) ;
const temp = ` ${ grantFile } . ${ process . pid } .tmp ` ;
fs . writeFileSync ( temp , JSON . stringify ( grant ) , { mode : 0o640 } ) ;
fs . renameSync ( temp , grantFile ) ;
return json ( res , 200 , { ok : true , repo , target , expires _at : grant . expires _at } ) ;
}
return json ( res , 404 , { error : "not_found" } ) ;
} catch ( error ) {
process . stderr . write ( ` lake-lamp request error: ${ String ( error && error . message || "unknown" ) . slice ( 0 , 240 ) } \n ` ) ;
return json ( res , error && error . code === "BODY_TOO_LARGE" ? 413 : 500 , { error : "request_failed" } ) ;
}
} ) ;
}
function approvalPage ( order , token ) {
return document ( "小湖灯授权请求" , `
< p class = "eyebrow" > LAKE LAMP SECURITY PROTOCOL < / p >
< h1 > 人格体请求进入一台服务器 < / h 1 >
< div class = "panel" >
< dl > < dt > 人格体 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . p e r s o n a . n a m e ) } < s m a l l > $ { e s c a p e H t m l ( o r d e r . p e r s o n a . p i d ) } < / s m a l l > < / d d >
< dt > 申请入口 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . p r o v e n a n c e & & o r d e r . p r o v e n a n c e . s y s t e m _ e n t r y | | " 旧 版 工 单 " ) } < / d d >
< dt > 实例来源 < / d t > < d d > $ { e s c a p e H t m l ( o r i g i n L a b e l ( o r d e r ) ) } < / d d >
< dt > 目标节点 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . t a r g e t ) } < / d d > < d t > 授 权 范 围 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . s c o p e ) } < / d d >
< dt > 进入动作 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . a c t i o n ) } < / d d > < d t > 会 话 能 力 < / d t > < d d > $ { e s c a p e H t m l ( ( o r d e r . a l l o w e d _ a c t i o n s | | [ o r d e r . a c t i o n ] ) . j o i n ( " · " ) ) } < / d d >
< dt > 绑定资源 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . r e s o u r c e | | " 无 " ) } < / d d >
< dt > 说明 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . d e s c r i p t i o n | | " 未 附 加 说 明 " ) } < / d d > < / d l >
< / d i v >
< p class = "notice" > 一次确认将打开这台服务器上的三小时受限运维会话 。 人格体持续执行已绑定任务时会自动续期 ; 切换服务器 、 扩大范围 、 切换绑定资源或停止活动后过期才需重新申请 。 < / p >
< form method = "post" > < button type = "submit" > 打开三小时受限运维会话 < / b u t t o n > < / f o r m >
` );
}
function requestPage ( order ) {
return document ( "小湖灯跨设备授权" , `
< p class = "eyebrow" > CROSS - DEVICE HANDOFF < / p >
< h1 > 核对这张无权限申请单 < / h 1 >
< div class = "panel" >
< dl > < dt > 人格体 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . p e r s o n a . n a m e ) } < s m a l l > $ { e s c a p e H t m l ( o r d e r . p e r s o n a . p i d ) } < / s m a l l > < / d d >
< dt > 申请入口 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . p r o v e n a n c e & & o r d e r . p r o v e n a n c e . s y s t e m _ e n t r y | | " 旧 版 工 单 " ) } < / d d >
< dt > 实例来源 < / d t > < d d > $ { e s c a p e H t m l ( o r i g i n L a b e l ( o r d e r ) ) } < / d d >
< dt > 目标节点 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . t a r g e t ) } < / d d > < d t > 授 权 范 围 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . s c o p e ) } < / d d >
< dt > 登记动作 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . a c t i o n ) } < / d d > < d t > 绑 定 资 源 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . r e s o u r c e | | " 无 " ) } < / d d > < d t > 说 明 < / d t > < d d > $ { e s c a p e H t m l ( o r d e r . d e s c r i p t i o n | | " 未 附 加 说 明 " ) } < / d d > < / d l >
< / d i v >
< p class = "notice" > 这张页面本身没有执行权 。 确认内容无误后 , 服务器只会向预登记邮箱发送一次真正的批准链接 。 < / p >
< form method = "post" > < button type = "submit" > 发送我的授权邮件 < / b u t t o n > < / f o r m >
` );
}
function emailSentPage ( order ) {
return document ( "授权邮件已发送" , ` <p class="eyebrow">OWNER VERIFICATION</p><h1>请打开邮箱完成批准</h1><div class="panel"><p>申请单已锁定到 <strong> ${ escapeHtml ( order && order . target || "登记节点" ) } </strong>。真正的批准链接只发送到服务器预登记邮箱。</p></div><p class="notice">批准后回到原来的 AI 对话,让它领取一次性会话。无需向 AI 提供验证码、密码或邮箱授权码。</p> ` ) ;
}
function requestErrorPage ( reason ) {
const messages = {
rate _limited : "请求过于频繁,请稍后再试。" ,
approval _email _already _sent : "授权邮件已经发送,请直接检查邮箱。" ,
authorization _email _failed : "授权邮件暂时发送失败,请稍后重试。" ,
} ;
if ( reason === "rate_limited" ) return document ( "发送频率保护" , ` <p class="eyebrow">RATE LIMIT · REQUEST KEPT</p><h1>小湖灯先替你守住这张申请单</h1><div class="panel"><p>当前网络在一小时内触发邮件的次数较多,发送动作被暂时暂停。</p></div><p class="notice">申请单本身没有被关闭。请稍后再试,或切换到手机流量后只点击一次。无需重新填写,也不要连续刷新。</p> ` ) ;
return document ( "申请单不可用" , ` <p class="eyebrow">REQUEST CLOSED</p><h1>这张申请单现在不能继续</h1><p class="notice"> ${ escapeHtml ( messages [ reason ] || ` 原因: ${ reason } ` ) } </p> ` ) ;
}
function approvedPage ( order ) {
return document ( "授权完成" , ` <p class="eyebrow">THREE-HOUR OPS SESSION</p><h1>三小时运维会话已打开</h1><div class="panel"><p> ${ escapeHtml ( order . persona . name ) } 已获准在 <strong> ${ escapeHtml ( order . target ) } </strong> 上执行本范围内的已登记能力。</p></div><p class="notice">可以关闭本页面。人格体持续执行原绑定任务时会自动续期;切换服务器、扩大范围、切换绑定资源或停止活动后过期才重新授权。</p> ` ) ;
}
function approvalErrorPage ( reason ) {
return document ( "链接不可用" , ` <p class="eyebrow">LINK CLOSED</p><h1>这条授权链接已经失效</h1><p class="notice">原因: ${ escapeHtml ( reason ) } 。如仍需操作,请让人格体重新提交工单。</p> ` ) ;
}
function document ( title , body ) {
return ` <!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title> ${ escapeHtml ( title ) } · 光湖</title><style>
: root { color - scheme : dark } * { box - sizing : border - box } body { margin : 0 ; min - height : 100 vh ; display : grid ; place - items : center ; background : radial - gradient ( circle at 20 % 10 % , # 17344 d , # 09111 b 55 % , # 05090 e ) ; color : # eaf4fb ; font : 16 px / 1.7 - apple - system , BlinkMacSystemFont , "Segoe UI" , sans - serif ; padding : 24 px } . shell { width : min ( 680 px , 100 % ) ; padding : 42 px ; border : 1 px solid # 29475 d ; border - radius : 24 px ; background : rgba ( 10 , 22 , 33 , . 94 ) ; box - shadow : 0 24 px 80 px # 0008 } . eyebrow { color : # 6 ed5ff ; letter - spacing : . 18 em ; font - size : 12 px } h1 { font - size : clamp ( 30 px , 6 vw , 48 px ) ; line - height : 1.15 ; margin : 10 px 0 28 px } . panel { background : # 102638 ; border : 1 px solid # 24465 d ; border - radius : 16 px ; padding : 20 px 24 px } dl { display : grid ; grid - template - columns : 110 px 1 fr ; gap : 12 px ; margin : 0 } dt { color : # 8 ba4b6 } dd { margin : 0 ; font - weight : 650 } small { display : block ; color : # 7893 a6 ; font - weight : 400 } . notice { color : # 9 eb2c0 ; margin : 20 px 0 } button { width : 100 % ; border : 0 ; border - radius : 14 px ; padding : 16 px ; background : # 67 d4ff ; color : # 042235 ; font - weight : 800 ; font - size : 17 px ; cursor : pointer } @ media ( max - width : 520 px ) { . shell { padding : 28 px 22 px } dl { grid - template - columns : 1 fr ; gap : 2 px } dd { margin - bottom : 12 px } }
< / s t y l e > < / h e a d > < b o d y > < m a i n c l a s s = " s h e l l " > $ { b o d y } < / m a i n > < / b o d y > < / h t m l > ` ;
}
function readJson ( req ) {
return new Promise ( ( resolve , reject ) => {
let raw = "" ;
req . on ( "data" , chunk => { raw += chunk ; if ( raw . length > 32 * 1024 ) { const error = new Error ( "body too large" ) ; error . code = "BODY_TOO_LARGE" ; reject ( error ) ; req . destroy ( ) ; } } ) ;
req . on ( "end" , ( ) => { try { resolve ( JSON . parse ( raw || "{}" ) ) ; } catch { resolve ( null ) ; } } ) ;
req . on ( "error" , reject ) ;
} ) ;
}
function bearer ( req ) { return String ( req . headers . authorization || "" ) . replace ( /^Bearer\s+/i , "" ) ; }
function bearerMatches ( req , expected ) { return Boolean ( expected ) && safeEqual ( bearer ( req ) , expected ) ; }
function safeEqual ( left , right ) { const a = Buffer . from ( String ( left ) ) ; const b = Buffer . from ( String ( right ) ) ; return a . length === b . length && crypto . timingSafeEqual ( a , b ) ; }
function sha256 ( value ) { return crypto . createHash ( "sha256" ) . update ( String ( value ) ) . digest ( "hex" ) ; }
function splitCsv ( value ) { return value . split ( "," ) . map ( item => item . trim ( ) ) . filter ( Boolean ) ; }
function loadApprovers ( file , ownerEmail ) {
if ( ! file ) return ownerEmail ? [ { id : "sovereign-owner" , email : ownerEmail , default : true , persona _ids : [ ] , targets : [ "*" ] , scopes : [ "*" ] } ] : [ ] ;
const parsed = JSON . parse ( fs . readFileSync ( file , "utf8" ) ) ;
if ( ! parsed || ! Array . isArray ( parsed . approvers ) ) throw new Error ( "invalid approver registry" ) ;
return parsed . approvers . filter ( item => item && validEmail ( item . email ) ) . map ( item => ( {
id : String ( item . id || "" ) , email : item . email , default : item . default === true ,
persona _ids : Array . isArray ( item . persona _ids ) ? item . persona _ids . map ( String ) : [ ] ,
targets : Array . isArray ( item . targets ) ? item . targets . map ( String ) : [ ] ,
scopes : Array . isArray ( item . scopes ) ? item . scopes . map ( String ) : [ ] ,
} ) ) ;
}
function selectApprover ( approvers , order ) {
const eligible = approvers . filter ( item => matches ( item . targets , order . target ) && matches ( item . scopes , order . scope ) ) ;
return eligible . find ( item => item . persona _ids . includes ( order . persona . pid ) ) || eligible . find ( item => item . default ) || null ;
}
function matches ( values , value ) { return values . includes ( "*" ) || values . includes ( value ) ; }
function validEmail ( value ) { return typeof value === "string" && value . length <= 254 && /^[^@\s]+@[^@\s]+$/ . test ( value ) ; }
function clientAddress ( req ) {
const forwarded = String ( req . headers [ "x-forwarded-for" ] || "" ) . split ( "," ) . map ( value => value . trim ( ) ) . filter ( Boolean ) ;
return String ( forwarded [ forwarded . length - 1 ] || req . socket . remoteAddress || "unknown" ) . slice ( 0 , 96 ) ;
}
function validateWorkorderBody ( body , targets , actions ) {
if ( body . email || body . recipient || body . smtp _pass ) return { ok : false , status : 400 , error : "direct_recipient_forbidden" } ;
if ( ! body . persona _id || ! body . target || ! body . scope || ! body . action ) return { ok : false , status : 400 , error : "missing_required_field" } ;
const personaId = String ( body . persona _id ) ;
const personaName = String ( body . persona _name || personaId ) ;
const target = String ( body . target ) ;
const scope = String ( body . scope ) ;
const action = String ( body . action ) ;
const description = String ( body . description || "" ) ;
const resource = String ( body . resource || "" ) ;
const provenance = {
system _entry : String ( body . system _entry || "" ) ,
software : String ( body . origin _software || "" ) ,
model : String ( body . origin _model || "" ) ,
instance : String ( body . origin _instance || "" ) ,
} ;
if ( ! /^[A-Za-z0-9._:+\u221e-]{2,80}$/ . test ( personaId ) || personaName . length > 100 || description . length > 500 ) return { ok : false , status : 400 , error : "invalid_request_fields" } ;
if ( ! targets . has ( target ) ) return { ok : false , status : 400 , error : "unknown_target" } ;
if ( ! Array . isArray ( actions [ scope ] ) || ! actions [ scope ] . includes ( action ) ) return { ok : false , status : 400 , error : "unknown_or_mismatched_action" } ;
if ( action === "provision-approved-architecture" && ! /^[A-Z0-9][A-Z0-9._-]{5,119}@[0-9a-f]{40}$/ . test ( resource ) ) return { ok : false , status : 400 , error : "immutable_architecture_resource_required" } ;
if ( action !== "provision-approved-architecture" && resource ) return { ok : false , status : 400 , error : "resource_not_allowed_for_action" } ;
if ( Object . values ( provenance ) . some ( Boolean ) && ( provenance . system _entry !== "光湖语言人格系统当前实例" || Object . values ( provenance ) . some ( item => ! item || item . length > 120 ) ) ) return { ok : false , status : 400 , error : "invalid_instance_provenance" } ;
return { ok : true , request : { persona : { pid : personaId , name : personaName } , provenance , target , scope , action , allowedActions : actions [ scope ] , description , resource } } ;
}
function originLabel ( order ) {
const value = order && order . provenance || { } ;
return value . software || value . model || value . instance ? ` ${ value . software || "未知软件" } · ${ value . model || "未知模型" } · ${ value . instance || "当前实例" } ` : "旧版工单未记录" ;
}
class SlidingWindowLimiter {
constructor ( limit , windowSeconds ) { this . limit = Math . max ( 1 , limit ) ; this . windowMs = windowSeconds * 1000 ; this . events = new Map ( ) ; this . calls = 0 ; }
take ( key , now = Date . now ( ) ) {
this . calls += 1 ;
if ( this . calls % 256 === 0 ) {
for ( const [ storedKey , values ] of this . events ) {
const active = values . filter ( value => now - value < this . windowMs ) ;
if ( active . length ) this . events . set ( storedKey , active ) ; else this . events . delete ( storedKey ) ;
}
}
const recent = ( this . events . get ( key ) || [ ] ) . filter ( value => now - value < this . windowMs ) ;
if ( recent . length >= this . limit ) { this . events . set ( key , recent ) ; return false ; }
recent . push ( now ) ; this . events . set ( key , recent ) ; return true ;
}
}
function escapeHtml ( value ) { return String ( value ) . replace ( /[&<>"']/g , char => ( { "&" : "&" , "<" : "<" , ">" : ">" , '"' : """ , "'" : "'" } ) [ char ] ) ; }
function json ( res , status , value ) { res . writeHead ( status , { "content-type" : "application/json; charset=utf-8" , "cache-control" : "no-store" , "x-content-type-options" : "nosniff" } ) ; res . end ( JSON . stringify ( value ) ) ; }
function html ( res , status , value ) { res . writeHead ( status , { "content-type" : "text/html; charset=utf-8" , "cache-control" : "no-store" , "content-security-policy" : "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'" , "referrer-policy" : "no-referrer" , "x-content-type-options" : "nosniff" } ) ; res . end ( value ) ; }
if ( require . main === module ) {
const host = process . env . LAKE _LAMP _HOST || "127.0.0.1" ;
const port = Number ( process . env . LAKE _LAMP _PORT || 3921 ) ;
createApp ( ) . listen ( port , host , ( ) => process . stdout . write ( ` lake-lamp-authz listening on ${ host } : ${ port } \n ` ) ) ;
}
module . exports = { createApp , DEFAULT _ACTIONS , SlidingWindowLimiter , loadApprovers , selectApprover } ;