feat(lake-lamp): publish canonical code route guard
This commit is contained in:
parent
e80ee6d966
commit
e3cc40ecd3
3 changed files with 109 additions and 0 deletions
13
server-tools/lake-lamp-continuity-guard/README.md
Normal file
13
server-tools/lake-lamp-continuity-guard/README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# 小湖灯连续性守卫 · 代码频道策略
|
||||||
|
|
||||||
|
本目录保存小湖灯本地协调 Agent 已采用的可公开恢复策略:
|
||||||
|
|
||||||
|
- 代码频道 Web 根只有 `https://guanghulab.com/code/`。
|
||||||
|
- 当前只允许 REPO-012 与 REPO-014。
|
||||||
|
- HTTPS、`.git` 和 `repo://` 先归一化为同一个仓库身份。
|
||||||
|
- 实际写租约必须是 `repo://.../<repository>#<exact-branch>`。
|
||||||
|
- 旧 `/fifth-domain/`、其他主机、未登记仓库和含凭证 URL 失败关闭。
|
||||||
|
|
||||||
|
本模块是策略事实源和回归样例,不代表 JZAO 上的本地协调运行时已经部署到服务器。运行时
|
||||||
|
升级、仓库发布和服务器部署仍分别举证。
|
||||||
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
const HOST = "guanghulab.com";
|
||||||
|
const PREFIX = "/code/bingshuo/";
|
||||||
|
const REPOSITORIES = new Set([
|
||||||
|
"guanghu-ice-heart",
|
||||||
|
"hololake-system-architecture",
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function normalizeCodeChannelRepository(value) {
|
||||||
|
let url;
|
||||||
|
try {
|
||||||
|
url = new URL(String(value).trim().replace(/^repo:\/\//u, "https://"));
|
||||||
|
} catch {
|
||||||
|
throw new Error(
|
||||||
|
"INVALID_PUBLISH_REPOSITORY: use repo://guanghulab.com/code/bingshuo/<repository>",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (url.username || url.password) {
|
||||||
|
throw new Error("PUBLISH_REPOSITORY_CREDENTIALS_FORBIDDEN");
|
||||||
|
}
|
||||||
|
const pathname = url.pathname.replace(/\.git$/u, "").replace(/\/+$/u, "");
|
||||||
|
const slug = pathname.startsWith(PREFIX)
|
||||||
|
? pathname.slice(PREFIX.length)
|
||||||
|
: "";
|
||||||
|
if (url.hostname !== HOST || !REPOSITORIES.has(slug)) {
|
||||||
|
throw new Error(
|
||||||
|
"NON_CANONICAL_CODE_CHANNEL_REPOSITORY: only the two registered /code/ repositories are current",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return `repo://${HOST}${PREFIX}${slug}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizePublishTarget(value = "main") {
|
||||||
|
const target = String(value).trim() || "main";
|
||||||
|
if (
|
||||||
|
!/^(?!\/)(?!.*(?:\.\.|\/\/|@\{|[~^:?*\[\\]))[A-Za-z0-9._/-]+$/u.test(
|
||||||
|
target,
|
||||||
|
) ||
|
||||||
|
target.endsWith("/") ||
|
||||||
|
target.endsWith(".")
|
||||||
|
) {
|
||||||
|
throw new Error("INVALID_PUBLISH_TARGET: use an exact Git branch name");
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function publishLeaseResource(repository, target = "main") {
|
||||||
|
return `${normalizeCodeChannelRepository(repository)}#${normalizePublishTarget(target)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const currentCodeChannelRepositories = Object.freeze([
|
||||||
|
"repo://guanghulab.com/code/bingshuo/guanghu-ice-heart",
|
||||||
|
"repo://guanghulab.com/code/bingshuo/hololake-system-architecture",
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import test from "node:test";
|
||||||
|
import {
|
||||||
|
currentCodeChannelRepositories,
|
||||||
|
normalizeCodeChannelRepository,
|
||||||
|
publishLeaseResource,
|
||||||
|
} from "./code-channel-policy.mjs";
|
||||||
|
|
||||||
|
test("HTTPS, .git and repo forms resolve to one repository identity", () => {
|
||||||
|
const expected =
|
||||||
|
"repo://guanghulab.com/code/bingshuo/guanghu-ice-heart";
|
||||||
|
assert.equal(
|
||||||
|
normalizeCodeChannelRepository(
|
||||||
|
"https://guanghulab.com/code/bingshuo/guanghu-ice-heart.git",
|
||||||
|
),
|
||||||
|
expected,
|
||||||
|
);
|
||||||
|
assert.equal(normalizeCodeChannelRepository(expected), expected);
|
||||||
|
assert.equal(publishLeaseResource(expected), `${expected}#main`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("only the two current repositories are allowed", () => {
|
||||||
|
assert.equal(currentCodeChannelRepositories.length, 2);
|
||||||
|
for (const invalid of [
|
||||||
|
"https://guanghulab.com/fifth-domain/bingshuo/fifth-domain.git",
|
||||||
|
"https://guanghubingshuo.com/code/bingshuo/guanghulab.git",
|
||||||
|
"repo://guanghulab.com/code/bingshuo/unknown",
|
||||||
|
]) {
|
||||||
|
assert.throws(() => normalizeCodeChannelRepository(invalid));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("credential-bearing remotes are rejected", () => {
|
||||||
|
assert.throws(
|
||||||
|
() =>
|
||||||
|
normalizeCodeChannelRepository(
|
||||||
|
"https://user:secret@guanghulab.com/code/bingshuo/guanghu-ice-heart.git",
|
||||||
|
),
|
||||||
|
/CREDENTIALS_FORBIDDEN/u,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
Loading…
Reference in a new issue