Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ methodology, followed by a fix wave that touched every chapter.
layer (the former multi-format and schema pages, merged) plus five
behavioral surfaces; the command-line page rebuilt around the actual
decode workflow (UTF-16LE, abbreviated flags, the 4688 command-line gap).
- The linear reading arc flows section-to-section: the Alert chapter's
thirteen subsection reference pages step out of the previous/next pager
(they are reached from their section pages and render no pager of their
own), so reading straight through no longer detours into deep reference
material.
- Altitude honesty pass: Tier 3 redefined as senior technical escalation
with incident command as a separate function; program-level content
(telemetry principles, the intel pipeline, dark-web monitoring, insider
Expand Down Expand Up @@ -171,6 +176,11 @@ methodology, followed by a fix wave that touched every chapter.
The five guide pages (Fast path, AI triage, Cognitive traps, Quick
reference, Where ASSURED sits) now fold into a Guides dropdown, restoring
the eleven-item row the 1350px breakpoint was calibrated for.
- Laptops get the desktop navigation instead of the phone menu: the
eleven-link header now fits from 1240px up, using tighter spacing and an
icon-only search trigger at laptop widths (1240 to 1449px), with the full
search label returning at 1450px. The hamburger menu is reserved for
phones and tablets.
- The progress strip on a quiz's own page ticks the moment the chapter quiz
completes instead of after a reload; quiz-completion storage now lives in
one shared module read by both the quiz and the strip.
Expand All @@ -186,7 +196,8 @@ methodology, followed by a fix wave that touched every chapter.
themselves current for every child page.
- The Alert dropdown lists its three sections like every other chapter
instead of every subsection page; subsection navigation stays on the
section pages themselves.
section pages themselves. The mobile menu now matches, and its section
rows stay highlighted while reading a subsection.
- The CDE and PFI hover tooltips on the regulatory-boundaries page show
their definitions for the first time; the term text passed as slot
children had always replaced the definition body. The DefineTerm doc
Expand Down
21 changes: 10 additions & 11 deletions astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
import { defineConfig } from "astro/config";
import tailwindcss from "@tailwindcss/vite";
import mdx from "@astrojs/mdx";
import remarkGfm from 'remark-gfm';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import remarkGfm from "remark-gfm";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import sitemap from "@astrojs/sitemap";

// https://astro.build/config
export default defineConfig({

site: 'https://assured-methodology.vercel.app',
base: '/',
site: "https://assured-methodology.vercel.app",
base: "/",
// Vercel serves the trailing-slash form (vercel.json "trailingSlash": true)
// and 308-redirects the bare form. "always" makes dev 404 the bare form so
// a link written without the slash fails loudly before it ships.
trailingSlash: 'always',
trailingSlash: "always",
// Legacy-URL redirects live in vercel.json (server-side 308s), not here:
// Astro's static redirects emit meta-refresh stub pages without an <html>
// element, and inbound legacy links are a production concern anyway.
Expand All @@ -34,9 +33,9 @@ export default defineConfig({
// The site is dark-only; a single dark theme keeps code blocks from
// rendering on a white background (the old dual-theme config defaulted
// to github-light and nothing ever switched it).
theme: 'github-dark',
wrap: true
}
theme: "github-dark",
wrap: true,
},
},
vite: {
plugins: [tailwindcss()],
Expand All @@ -46,4 +45,4 @@ export default defineConfig({
},
},
},
});
});
10 changes: 8 additions & 2 deletions scripts/check-csp.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ function main() {
.flatMap((h) => h.headers ?? [])
.find((h) => h.key === "Content-Security-Policy");
if (!rule) {
console.error("check-csp: no Content-Security-Policy header in vercel.json");
console.error(
"check-csp: no Content-Security-Policy header in vercel.json",
);
process.exit(1);
}

Expand All @@ -86,7 +88,11 @@ function main() {
.split(/\s+/)
.slice(1)
.filter((src) => !src.startsWith("'sha256-"));
directives[scriptIdx] = ["script-src", ...keep, ...[...built.keys()].sort()].join(" ");
directives[scriptIdx] = [
"script-src",
...keep,
...[...built.keys()].sort(),
].join(" ");
rule.value = directives.join("; ");
writeFileSync(VERCEL_JSON, `${JSON.stringify(config, null, 2)}\n`);
console.log(`check-csp: wrote ${built.size} script hashes to vercel.json`);
Expand Down
23 changes: 17 additions & 6 deletions scripts/check-links.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ function idsIn(html) {

function hrefsIn(html) {
const hrefs = [];
for (const m of html.matchAll(/<a\b[^>]*\bhref\s*=\s*("([^"]*)"|'([^']*)')/gi)) {
for (const m of html.matchAll(
/<a\b[^>]*\bhref\s*=\s*("([^"]*)"|'([^']*)')/gi,
)) {
hrefs.push(decodeEntities(m[2] ?? m[3]));
}
return hrefs;
Expand All @@ -78,7 +80,8 @@ function main() {
const files = htmlFiles(DIST);
const idCache = new Map(); // html file -> Set of ids
const idsOf = (file) => {
if (!idCache.has(file)) idCache.set(file, idsIn(readFileSync(file, "utf8")));
if (!idCache.has(file))
idCache.set(file, idsIn(readFileSync(file, "utf8")));
return idCache.get(file);
};

Expand All @@ -97,13 +100,17 @@ function main() {
// Same-page fragment ("#risk-matrix") or bare "#" (top of page).
if (pathname === "") {
if (fragment && !idsOf(file).has(decodeURIComponent(fragment))) {
broken.push(`${pagePath} -> ${raw} (no id "${fragment}" on this page)`);
broken.push(
`${pagePath} -> ${raw} (no id "${fragment}" on this page)`,
);
}
continue;
}

if (!pathname.startsWith("/")) {
broken.push(`${pagePath} -> ${raw} (relative link; use a root-relative path)`);
broken.push(
`${pagePath} -> ${raw} (relative link; use a root-relative path)`,
);
continue;
}

Expand All @@ -124,13 +131,17 @@ function main() {
continue;
}
if (fragment && !idsOf(target).has(decodeURIComponent(fragment))) {
broken.push(`${pagePath} -> ${raw} (no id "${fragment}" on target page)`);
broken.push(
`${pagePath} -> ${raw} (no id "${fragment}" on target page)`,
);
}
}
}

if (broken.length === 0) {
console.log(`check-links: OK (${checked} internal links across ${files.length} pages)`);
console.log(
`check-links: OK (${checked} internal links across ${files.length} pages)`,
);
return;
}
for (const b of broken.sort()) console.error(`check-links: BROKEN ${b}`);
Expand Down
15 changes: 15 additions & 0 deletions scripts/check-reading-order.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ const EXEMPT_ROUTES = new Set([
"/docs/glossaries/bad/",
"/docs/glossaries/cat/",
"/docs/glossaries/clear/",
// Alert subsection reference pages: reached from their section hubs, not
// part of the section-to-section reading arc.
"/docs/alert/detection-mechanisms/signature/",
"/docs/alert/detection-mechanisms/anomaly/",
"/docs/alert/detection-mechanisms/rule/",
"/docs/alert/detection-mechanisms/behavioral/",
"/docs/alert/validation/baseline-comparison/",
"/docs/alert/validation/attack-chains/",
"/docs/alert/validation/criticality/",
"/docs/alert/parsing/multi-format/",
"/docs/alert/parsing/command-line/",
"/docs/alert/parsing/process-relationships/",
"/docs/alert/parsing/network/",
"/docs/alert/parsing/file-system/",
"/docs/alert/parsing/cloud-identity/",
]);

function* mdxFiles(dir) {
Expand Down
Loading