chore: import upstream snapshot with attribution
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:23:53 +08:00
commit b3a7f98e5a
3020 changed files with 935484 additions and 0 deletions
@@ -0,0 +1,193 @@
import { describe, expect, it } from "vitest";
import {
CAPABILITY_RENAMES,
capabilitiesToDeclaredAccess,
declaredAccessToCapabilities,
isDeprecatedCapability,
normalizeCapabilities,
normalizeCapability,
} from "../src/index.js";
describe("isDeprecatedCapability", () => {
it("recognises every key of CAPABILITY_RENAMES as deprecated", () => {
for (const legacy of Object.keys(CAPABILITY_RENAMES)) {
expect(isDeprecatedCapability(legacy)).toBe(true);
}
});
it("does not flag any rename target as deprecated (renames must be terminal)", () => {
// If a rename target ended up as another deprecated name, normalization
// would never settle. Check the closure stops in one step.
for (const target of Object.values(CAPABILITY_RENAMES)) {
expect(isDeprecatedCapability(target)).toBe(false);
}
});
it("does not flag prototype property names as deprecated", () => {
// Object.hasOwn guard: prototype keys must not slip through.
expect(isDeprecatedCapability("toString")).toBe(false);
expect(isDeprecatedCapability("constructor")).toBe(false);
expect(isDeprecatedCapability("__proto__")).toBe(false);
});
});
describe("normalizeCapability", () => {
it("rewrites every legacy name to its replacement", () => {
for (const [legacy, replacement] of Object.entries(CAPABILITY_RENAMES)) {
expect(normalizeCapability(legacy)).toBe(replacement);
}
});
it("passes current names through unchanged", () => {
expect(normalizeCapability("network:request")).toBe("network:request");
expect(normalizeCapability("content:read")).toBe("content:read");
});
it("passes unknown strings through unchanged for downstream validators", () => {
expect(normalizeCapability("not:a:real:cap")).toBe("not:a:real:cap");
});
});
describe("normalizeCapabilities", () => {
it("preserves order of first appearance", () => {
expect(normalizeCapabilities(["content:read", "network:request", "media:read"])).toEqual([
"content:read",
"network:request",
"media:read",
]);
});
it("collapses a legacy name into its canonical equivalent", () => {
expect(normalizeCapabilities(["read:content"])).toEqual(["content:read"]);
});
it("deduplicates when a manifest declares both the legacy and canonical forms", () => {
// Both `network:fetch` and `network:request` are present -- after
// normalization both become `network:request`, and the second occurrence
// is dropped.
expect(normalizeCapabilities(["network:fetch", "network:request"])).toEqual([
"network:request",
]);
expect(normalizeCapabilities(["network:request", "network:fetch"])).toEqual([
"network:request",
]);
});
it("handles an empty array", () => {
expect(normalizeCapabilities([])).toEqual([]);
});
});
describe("declaredAccess facet mapping", () => {
it("maps each hook-registration capability to its participation facet", () => {
expect(capabilitiesToDeclaredAccess(["hooks.email-transport:register"], [])).toEqual({
email: { transport: {} },
});
expect(capabilitiesToDeclaredAccess(["hooks.email-events:register"], [])).toEqual({
email: { events: {} },
});
expect(capabilitiesToDeclaredAccess(["hooks.page-fragments:register"], [])).toEqual({
page: { fragments: {} },
});
expect(capabilitiesToDeclaredAccess(["users:read"], [])).toEqual({ users: { read: {} } });
expect(capabilitiesToDeclaredAccess(["taxonomies:read"], [])).toEqual({
taxonomies: { read: {} },
});
});
it("distinguishes host-restricted from unrestricted network", () => {
expect(capabilitiesToDeclaredAccess(["network:request"], ["api.example.com"])).toEqual({
network: { request: { allowedHosts: ["api.example.com"] } },
});
// An empty constraint object is the lexicon's spelling of "unrestricted".
expect(
capabilitiesToDeclaredAccess(["network:request:unrestricted", "network:request"], []),
).toEqual({ network: { request: {} } });
});
it("never widens an empty allowedHosts (deny-all) to unrestricted", () => {
// An empty allowedHosts is the most-restrictive spelling (deny-all); it must
// never decode to unrestricted, or the tightest declaration grants the most.
expect(capabilitiesToDeclaredAccess(["network:request"], [])).toEqual({
network: { request: { allowedHosts: [] } },
});
const decoded = declaredAccessToCapabilities({ network: { request: { allowedHosts: [] } } });
expect(decoded.capabilities).not.toContain("network:request:unrestricted");
expect(decoded).toEqual({ capabilities: ["network:request"], allowedHosts: [] });
});
it("carries every facet of an email transport that also calls out and observes events", () => {
// declaredAccess must carry all three facets so the consent list matches
// the capability set the runtime enforces.
const da = capabilitiesToDeclaredAccess(
["hooks.email-transport:register", "network:request", "hooks.email-events:register"],
["api.cloudflare.com"],
);
expect(da).toEqual({
network: { request: { allowedHosts: ["api.cloudflare.com"] } },
email: { transport: {}, events: {} },
});
expect(new Set(declaredAccessToCapabilities(da).capabilities)).toEqual(
new Set(["hooks.email-transport:register", "network:request", "hooks.email-events:register"]),
);
});
});
describe("declaredAccess <-> capabilities round-trip (total over the vocabulary)", () => {
// The full enumeration of implication-closed, valid capability states.
// definePlugin closes write->read and unrestricted->request, and publish
// rejects network:request with no hosts, so these are the only states that
// can reach a published manifest. Every one must round-trip to identity --
// the guard that the two representations are isomorphic, so the consent list
// always equals the capability set the runtime enforces.
const contentChoices = [[], ["content:read"], ["content:read", "content:write"]];
const mediaChoices = [[], ["media:read"], ["media:read", "media:write"]];
const networkChoices: { caps: string[]; hosts: string[] }[] = [
{ caps: [], hosts: [] },
{ caps: ["network:request", "network:request:unrestricted"], hosts: [] },
// Host-restricted with an empty allow-list = deny-all. Must round-trip
// as restricted, never widening to unrestricted.
{ caps: ["network:request"], hosts: [] },
{ caps: ["network:request"], hosts: ["api.example.com"] },
{ caps: ["network:request"], hosts: ["api.example.com", "*.cdn.example.com"] },
];
const singletonFacets = [
"email:send",
"hooks.email-events:register",
"hooks.email-transport:register",
"hooks.page-fragments:register",
"users:read",
"taxonomies:read",
];
function* states() {
for (const content of contentChoices) {
for (const media of mediaChoices) {
for (const network of networkChoices) {
for (let mask = 0; mask < 1 << singletonFacets.length; mask++) {
const extra = singletonFacets.filter((_, i) => mask & (1 << i));
yield {
capabilities: [...content, ...media, ...network.caps, ...extra],
allowedHosts: network.hosts,
};
}
}
}
}
}
it("recovers every implication-closed valid state exactly", () => {
let count = 0;
for (const input of states()) {
const back = declaredAccessToCapabilities(
capabilitiesToDeclaredAccess(input.capabilities, input.allowedHosts),
);
expect(new Set(back.capabilities)).toEqual(new Set(input.capabilities));
expect(new Set(back.allowedHosts)).toEqual(new Set(input.allowedHosts));
count++;
}
// 3 content x 3 media x 5 network x 2^6 singleton subsets.
expect(count).toBe(2880);
});
});
@@ -0,0 +1,133 @@
import { describe, expect, it } from "vitest";
import {
deriveSlugFromId,
isPluginSlug,
isPluginVersion,
PLUGIN_SLUG_MAX_LENGTH,
PLUGIN_VERSION_MAX_LENGTH,
} from "../src/index.js";
describe("deriveSlugFromId", () => {
it("strips a leading @ and replaces / with -", () => {
expect(deriveSlugFromId("@emdash-cms/gallery")).toBe("emdash-cms-gallery");
});
it("passes through a slug-shaped id unchanged", () => {
expect(deriveSlugFromId("gallery")).toBe("gallery");
});
it("does not normalise case (caller must follow up with isPluginSlug)", () => {
// `Gallery` is not a valid slug; this helper only does the mechanical
// scoped-name translation. Callers must reject the result if it fails
// `isPluginSlug`.
expect(deriveSlugFromId("@Acme/Gallery")).toBe("Acme-Gallery");
});
});
describe("isPluginSlug", () => {
it("accepts canonical slugs", () => {
expect(isPluginSlug("gallery")).toBe(true);
expect(isPluginSlug("emdash-cms-gallery")).toBe(true);
expect(isPluginSlug("a")).toBe(true);
expect(isPluginSlug("a1_2-3")).toBe(true);
});
it("rejects empty strings", () => {
expect(isPluginSlug("")).toBe(false);
});
it("rejects slugs that don't start with a lowercase letter", () => {
expect(isPluginSlug("1plugin")).toBe(false);
expect(isPluginSlug("-plugin")).toBe(false);
expect(isPluginSlug("_plugin")).toBe(false);
expect(isPluginSlug("Plugin")).toBe(false);
});
it("rejects slugs containing forbidden characters", () => {
expect(isPluginSlug("Plugin/Foo")).toBe(false);
expect(isPluginSlug("foo bar")).toBe(false);
expect(isPluginSlug("foo.bar")).toBe(false);
expect(isPluginSlug("foo:bar")).toBe(false);
expect(isPluginSlug("foo@bar")).toBe(false);
expect(isPluginSlug("🦀plugin")).toBe(false);
});
it("rejects slugs over the max length", () => {
expect(isPluginSlug("a".repeat(PLUGIN_SLUG_MAX_LENGTH))).toBe(true);
expect(isPluginSlug("a".repeat(PLUGIN_SLUG_MAX_LENGTH + 1))).toBe(false);
});
});
describe("isPluginVersion", () => {
it("accepts canonical semver versions", () => {
expect(isPluginVersion("1.0.0")).toBe(true);
expect(isPluginVersion("0.0.1-alpha.0")).toBe(true);
expect(isPluginVersion("10.20.30")).toBe(true);
});
it("accepts canonical pre-release identifiers per semver 2.0", () => {
expect(isPluginVersion("1.0.0-rc.1")).toBe(true);
expect(isPluginVersion("1.0.0-alpha")).toBe(true);
expect(isPluginVersion("1.0.0-alpha.1")).toBe(true);
expect(isPluginVersion("1.0.0-0.3.7")).toBe(true);
expect(isPluginVersion("1.0.0-x.7.z.92")).toBe(true);
});
it("rejects build-metadata suffixes (semver `+` is disallowed)", () => {
expect(isPluginVersion("1.0.0+build")).toBe(false);
expect(isPluginVersion("1.0.0+build.1")).toBe(false);
expect(isPluginVersion("1.0.0-rc.0+build")).toBe(false);
});
it("rejects leading-zero numeric components (per semver)", () => {
expect(isPluginVersion("01.0.0")).toBe(false);
expect(isPluginVersion("1.02.0")).toBe(false);
expect(isPluginVersion("1.0.03")).toBe(false);
// Pre-release numerics also disallow leading zeros.
expect(isPluginVersion("1.0.0-01")).toBe(false);
expect(isPluginVersion("1.0.0-rc.01")).toBe(false);
});
it("rejects malformed versions the previous loose regex accepted", () => {
expect(isPluginVersion(".1.0.0")).toBe(false);
expect(isPluginVersion("1.0.0-")).toBe(false);
expect(isPluginVersion("-")).toBe(false);
expect(isPluginVersion(".")).toBe(false);
expect(isPluginVersion("foo")).toBe(false);
expect(isPluginVersion("1.0")).toBe(false); // missing patch
expect(isPluginVersion("1")).toBe(false);
// Note: `1.0.0--rc` is technically valid semver — `-rc` is an
// alphanumeric identifier with leading hyphen — even though it looks
// suspicious. We accept it.
expect(isPluginVersion("1.0.0--rc")).toBe(true);
});
it("rejects path-traversal and shell-control characters", () => {
expect(isPluginVersion("../etc/passwd")).toBe(false);
expect(isPluginVersion("1.0.0; rm -rf /")).toBe(false);
expect(isPluginVersion("1.0.0:tag")).toBe(false);
});
it("rejects underscore and tilde even though atproto rkeys would accept them", () => {
expect(isPluginVersion("1_0_0")).toBe(false);
expect(isPluginVersion("1~0~0")).toBe(false);
});
it("rejects empty strings", () => {
expect(isPluginVersion("")).toBe(false);
});
it("rejects versions over the max length", () => {
// Construct exactly-max-length: "1." repeated, capped to keep semver shape.
// Use a prerelease tail to inflate length within the format.
const shortValid = "1.0.0";
expect(isPluginVersion(shortValid)).toBe(true);
// Synthesize a max-length valid: "1.0.0-" + identifier of length (max-6).
const tail = "a".repeat(PLUGIN_VERSION_MAX_LENGTH - 6);
const exactlyMax = `1.0.0-${tail}`;
expect(exactlyMax.length).toBe(PLUGIN_VERSION_MAX_LENGTH);
expect(isPluginVersion(exactlyMax)).toBe(true);
expect(isPluginVersion(`${exactlyMax}b`)).toBe(false);
});
});