diff --git a/docs/contribution/diagrams.md b/docs/contribution/diagrams.md index d59924e..1a343ca 100644 --- a/docs/contribution/diagrams.md +++ b/docs/contribution/diagrams.md @@ -21,7 +21,7 @@ The standalone viewer provides pan/zoom, node inspection, search/focus, relation Create `diagrams/..json` using the matching schema and authoring guidance in `vendor/archify/schemas/` and `vendor/archify/references/`. Use stable IDs, explicit relationships, and honest evidence labels. Do not include private information merely because the source repository is private: Pages access is a separate platform policy. -Set `meta.output` to `static/diagrams//index.html`. The build validates the typed source with the upstream showcase profile, renders locally, checks the artifact, and publishes the standalone HTML and a downloadable JSON source. +Set `meta.output` to `static/diagrams//index.html`. The build validates the typed source with the upstream showcase profile, renders locally, checks the artifact, and publishes the standalone HTML. Editable JSON stays in the repository; the portal does not publish source-download files. ```sh pnpm diagrams:build @@ -37,7 +37,7 @@ import ArchifyDiagram from '@site/src/components/ArchifyDiagram'; ``` -Supply a text alternative below each diagram. The wrapper uses a local, base-path-aware iframe with a descriptive title, scripts and downloads enabled, and no same-origin or parent-navigation permissions. The Open full viewer button expands the diagram in a full-screen modal on the current page, with the same iframe sandbox. Close it with the Close button or Escape; focus returns to the opener. It does not open a new tab. The separate standalone HTML asset remains directly addressable and is not itself iframe-sandboxed, so publish only reviewed, trusted diagrams. Generated output is ignored by Git and rebuilt in CI. +Supply a text alternative below each diagram. The wrapper uses a local, base-path-aware iframe with a descriptive title, scripts and downloads enabled, and no same-origin or parent-navigation permissions. The top-right expand icon expands the diagram in a full-screen modal on the current page, with the same iframe sandbox. Close it with the Close button or Escape; focus returns to the opener. It does not open a new tab. The separate standalone HTML asset remains directly addressable and is not itself iframe-sandboxed, so publish only reviewed, trusted diagrams. Generated output is ignored by Git and rebuilt in CI. ## Integration boundaries diff --git a/docs/organization/collaboration.mdx b/docs/organization/collaboration.mdx new file mode 100644 index 0000000..d32cf5b --- /dev/null +++ b/docs/organization/collaboration.mdx @@ -0,0 +1,23 @@ +--- +title: Collaboration +description: How Eldorado departments combine their responsibilities to deliver shared business outcomes. +--- + +Departments collaborate around shared outcomes while retaining their own team ownership and accountability. See [Structure](./structure.mdx) for department and squad responsibilities. + +## How the departments work together + +| Business outcome | Collaboration | +| --- | --- | +| Better buyer experience | Product defines improvements; Technology delivers them; Operations brings customer feedback; Data & AI measures the result. | +| Stronger seller experience | Product and Technology develop seller tools; Operations supports sellers; Finance manages financial processes. | +| Safe and trustworthy trading | Risk & Fraud, Trust & Resolution, Architecture & Security, and Finance coordinate controls and incident responses. | +| Sustainable growth | Marketing develops demand; Product improves conversion and retention; Finance measures profitability. | +| AI-powered execution | Data & AI supports engineering and develops marketplace intelligence; Operations improves service and quality workflows. | + +Department leaders remain accountable for outcomes, controls and service quality as AI becomes part of everyday work. + +## Related pages + +- [Structure](./structure.mdx) — departments, squads and responsibilities. +- [SDLC — Software Delivery Life Cycle](./sdlc.mdx) — leadership and delivery responsibilities. diff --git a/docs/organization/sdlc.mdx b/docs/organization/sdlc.mdx new file mode 100644 index 0000000..3bdb2b4 --- /dev/null +++ b/docs/organization/sdlc.mdx @@ -0,0 +1,27 @@ +--- +title: SDLC — Software Delivery Life Cycle +sidebar_label: SDLC +description: Leadership, reporting lines and team responsibilities supporting software delivery at Eldorado. +--- + +import ArchifyDiagram from '@site/src/components/ArchifyDiagram'; + +Software delivery brings together Product and Technology, supported by the departments responsible for marketplace operations and growth. This page describes the leadership and delivery responsibilities that support that work. + +## Leadership and delivery structure + + + +The diagram shows management responsibility from leader to role or team: + +- **CTO → Head of Engineering → Group Engineering Managers → Engineering Managers → the Product Engineering team.** +- **CTO → AI Architect**, coordinating engineering AI enablement. +- **COO → Operational Quality**, providing independent quality oversight. +- **CMO → Brand Team Lead**, leading Brand & Community. + +Product and Technology retain separate team ownership and reporting lines. Their teams coordinate priorities, design, engineering, quality and data work to deliver business outcomes. + +## Related pages + +- [Structure](./structure.mdx) — departments, squads and responsibilities. +- [Collaboration](./collaboration.mdx) — how departments coordinate around business outcomes. diff --git a/docs/organization/structure.mdx b/docs/organization/structure.mdx index a30031d..a98bcd1 100644 --- a/docs/organization/structure.mdx +++ b/docs/organization/structure.mdx @@ -111,27 +111,7 @@ The CFO coordinates Finance & Accounting and works with executive leadership on HR partners with department leaders on team capacity and development. People Operations works with Platform & IT on employee onboarding, role changes and offboarding. -## Leadership and delivery structure +## Related pages - - -The diagram shows management responsibility from leader to role or team: - -- **CTO → Head of Engineering → Group Engineering Managers → Engineering Managers → the Product Engineering team.** -- **CTO → AI Architect**, coordinating engineering AI enablement. -- **COO → Operational Quality**, providing independent quality oversight. -- **CMO → Brand Team Lead**, leading Brand & Community. - -Product and Technology retain separate team ownership and reporting lines. Their teams coordinate priorities, design, engineering, quality and data work to deliver business outcomes. - -## How the departments work together - -| Business outcome | Collaboration | -| --- | --- | -| Better buyer experience | Product defines improvements; Technology delivers them; Operations brings customer feedback; Data & AI measures the result. | -| Stronger seller experience | Product and Technology develop seller tools; Operations supports sellers; Finance manages financial processes. | -| Safe and trustworthy trading | Risk & Fraud, Trust & Resolution, Architecture & Security, and Finance coordinate controls and incident responses. | -| Sustainable growth | Marketing develops demand; Product improves conversion and retention; Finance measures profitability. | -| AI-powered execution | Data & AI supports engineering and develops marketplace intelligence; Operations improves service and quality workflows. | - -Department leaders remain accountable for outcomes, controls and service quality as AI becomes part of everyday work. +- [Collaboration](./collaboration.mdx) — how departments work together on business outcomes. +- [SDLC — Software Delivery Life Cycle](./sdlc.mdx) — leadership and delivery responsibilities. diff --git a/scripts/build-diagrams.mjs b/scripts/build-diagrams.mjs index f445275..db264da 100644 --- a/scripts/build-diagrams.mjs +++ b/scripts/build-diagrams.mjs @@ -24,7 +24,6 @@ for (const file of readdirSync('diagrams').sort()) { run(['deliver',type,input,output,'--quality','showcase','--json']); run(['check',output,'--json','--require-provenance']); renameSync(`static/diagrams/${name}/index.delivery.json`, `.cache/archify/${name}.delivery.json`); - copyFileSync(input,`static/diagrams/${name}.json`); } copyFileSync('vendor/archify/LICENSE','static/diagrams/ARCHIFY-LICENSE.txt'); copyFileSync('vendor/archify/THIRD_PARTY_NOTICES.md','static/diagrams/THIRD-PARTY-NOTICES.md'); diff --git a/scripts/portal.test.mjs b/scripts/portal.test.mjs index 58b81f6..db8db31 100644 --- a/scripts/portal.test.mjs +++ b/scripts/portal.test.mjs @@ -20,6 +20,7 @@ test('real build removes stale diagrams, keeps receipts private and rejects coll writeSpec('old'); let result = build(); assert.equal(result.status,0,result.stderr); assert(existsSync(join(root,'static/diagrams/old/index.html'))); + assert(!existsSync(join(root,'static/diagrams/old.json'))); assert(!readdirSync(join(root,'static/diagrams'),{recursive:true}).some(p=>p.endsWith('.delivery.json'))); unlinkSync(join(root,'diagrams/old.architecture.json')); writeSpec('new'); @@ -42,7 +43,7 @@ test('three independent section menus and Structure first', () => { for (const section of ['Organization', 'Strategy', 'Contribution']) assert(config.includes(`label: '${section}'`)); assert(!config.includes("label: 'Documentation'")); assert(!config.includes("label: 'Maintainer guide'")); - assert(read('sidebars/organization.ts').includes("organizationSidebar: ['structure']")); + assert(read('sidebars/organization.ts').includes("organizationSidebar: ['structure', 'collaboration', 'sdlc']")); for (const section of ['organization','strategy','contribution']) assert(config.includes(`id: '${section}'`)); }); test('Archify is pinned, licensed and rebuilt, not a remote embed', () => { @@ -58,6 +59,11 @@ test('Archify is pinned, licensed and rebuilt, not a remote embed', () => { assert(wrapper.includes('showModal()') && wrapper.includes('onClose=')); assert(!wrapper.includes('target="_blank"')); assert(wrapper.includes('Close full-screen diagram')); + assert(!wrapper.includes('JSON source') && !wrapper.includes('download>')); + assert(!wrapper.includes('Open full viewer')); + assert(wrapper.includes('aria-label={`Expand ${title}`}')); + assert(wrapper.includes('aria-hidden="true"')); + assert(read('src/css/custom.css').includes('justify-content: flex-end')); }); test('Product owns two teams and Technology owns five separate teams', () => { const spec = JSON.parse(read('diagrams/organization-structure.architecture.json')); @@ -103,6 +109,22 @@ test('departments share one row and each has delivery teams below it', () => { assert(!(a.pos[0] < b.pos[0] + b.size[0] && a.pos[0] + a.size[0] > b.pos[0] && a.pos[1] < b.pos[1] + b.size[1] && a.pos[1] + a.size[1] > b.pos[1]), `${a.id} overlaps ${b.id}`); } }); +test('organization content is split into linked focused pages', () => { + const structure = read('docs/organization/structure.mdx'); + const collaboration = read('docs/organization/collaboration.mdx'); + const sdlc = read('docs/organization/sdlc.mdx'); + assert(!structure.includes('## How the departments work together')); + assert(!structure.includes('## Leadership and delivery structure')); + assert(!structure.includes('name="organization-reporting"')); + assert(collaboration.includes('## How the departments work together')); + for (const outcome of ['Better buyer experience', 'Stronger seller experience', 'Safe and trustworthy trading', 'Sustainable growth', 'AI-powered execution']) assert(collaboration.includes(outcome)); + assert(sdlc.includes('title: SDLC — Software Delivery Life Cycle')); + assert(sdlc.includes('name="organization-reporting"')); + for (const role of ['Head of Engineering', 'AI Architect', 'Operational Quality', 'Brand Team Lead']) assert(sdlc.includes(role)); + for (const [name, page] of [['structure',structure],['collaboration',collaboration],['sdlc',sdlc]]) { + for (const other of ['structure','collaboration','sdlc'].filter(n => n !== name)) assert(page.includes(`./${other}.mdx`)); + } +}); test('organization page presents an operating model, not research notes', () => { const page = read('docs/organization/structure.mdx'); assert(page.includes('operating model') && page.includes('## Departments and teams')); diff --git a/scripts/verify.mjs b/scripts/verify.mjs index b8392a1..01da2f6 100644 --- a/scripts/verify.mjs +++ b/scripts/verify.mjs @@ -16,7 +16,7 @@ const workflow = read('.gitea/workflows/pages.yml'); assert(workflow.includes('mountpoint -q')); assert(workflow.includes("gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'")); if (process.argv.includes('--build')) { - for (const route of ['index.html','docs/overview/index.html','docs/maintain/index.html','docs/reference/index.html','404.html','organization/structure/index.html','strategy/index.html','contribution/index.html','contribution/diagrams/index.html','diagrams/organization-structure/index.html']) { + for (const route of ['index.html','docs/overview/index.html','docs/maintain/index.html','docs/reference/index.html','404.html','organization/structure/index.html','organization/collaboration/index.html','organization/sdlc/index.html','strategy/index.html','contribution/index.html','contribution/diagrams/index.html','diagrams/organization-structure/index.html']) { assert(existsSync(join('build',route)), `Missing route: ${route}`); } assert(!readdirSync('build/diagrams', {recursive: true}).some(f => f.endsWith('.delivery.json')), 'Private build receipts must not be published'); diff --git a/sidebars/organization.ts b/sidebars/organization.ts index 18dab5f..82f6909 100644 --- a/sidebars/organization.ts +++ b/sidebars/organization.ts @@ -1,2 +1,2 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; -export default {organizationSidebar: ['structure']} satisfies SidebarsConfig; +export default {organizationSidebar: ['structure', 'collaboration', 'sdlc']} satisfies SidebarsConfig; diff --git a/src/components/ArchifyDiagram/index.tsx b/src/components/ArchifyDiagram/index.tsx index 10a67c2..8c6467a 100644 --- a/src/components/ArchifyDiagram/index.tsx +++ b/src/components/ArchifyDiagram/index.tsx @@ -1,10 +1,9 @@ import React, {useEffect, useId, useRef, useState} from 'react'; import useBaseUrl from '@docusaurus/useBaseUrl'; -export default function ArchifyDiagram({name, title}: {name: string; title: string}): React.ReactElement { +export default function ArchifyDiagram({name, title, compact = false}: {name: string; title: string; compact?: boolean}): React.ReactElement { if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) throw new Error('Invalid diagram name'); const source = useBaseUrl(`/diagrams/${name}/`); - const json = useBaseUrl(`/diagrams/${name}.json`); const dialog = useRef(null); const opener = useRef(null); const headingId = useId(); @@ -17,8 +16,8 @@ export default function ArchifyDiagram({name, title}: {name: string; title: stri return () => {document.body.style.overflow = previousOverflow;}; }, [expanded]); const close = () => {dialog.current?.close();}; - return
-
Interactive diagram
JSON source ↓
+ return
+