132 KiB
Luca Pîslaru Portfolio Journey — Design Specification
Status: Approved design specification — independent review closed; ready for implementation planning
Date: 2026-09-01
Product type: Pre-rendered single-page document with progressive Vue enhancement
Primary audience: Hiring managers and technical interviewers
Revision note: This revision preserves the approved creative direction and closes the final confirmation blockers around byte-canonical approval artifacts, exact four-input provenance, signer-verifiable evidence, expiry and issuer recovery, atomic public visibility, literal physical input, and per-action latency oracles. It supersedes the earlier copy stored outside the Portfolio project.
1. Product definition
Build a distinctive personal portfolio for Luca Pîslaru, positioned equally as a System Administrator & Full-Stack Developer. The experience combines a restrained, highly readable professional interface with one deliberately expressive exception: a continuous retro-futuristic night-drive scene that turns page navigation into a journey.
The result must demonstrate technical range without looking theatrical, immature, or generated from a generic AI template. The animated world supplies personality; the content panels supply credibility. Visitors who ignore the scene must still receive a fast, complete, semantic, accessible portfolio.
This is a new code-based direction. The existing Figma file remains unchanged and is not an implementation source of truth.
2. Goals and non-goals
Goals
- Present systems administration and software development as equal halves of one professional identity.
- Give hiring managers a quick, credible overview while rewarding technical readers with meaningful implementation detail.
- Make the experience memorable through an original moving-road metaphor, chase-view car, route progression, and section signs.
- Use authentic project media and technical diagrams instead of decorative generated imagery.
- Work well with keyboard navigation, screen readers, reduced-motion settings, touch devices, and low-powered hardware.
- Ship search-engine-readable content in the first HTML response and make Luca's canonical public identity unambiguous.
- Keep unreleased projects private while still communicating their technical scope.
Non-goals
- No portrait.
- No GitHub heatmap, commit streak, fake activity, skill percentages, or invented metrics.
- No downloadable CV. Interested visitors are asked to contact Luca for a current or role-specific CV.
- No fake terminal session, command prompt gimmick, or wall of neon interface chrome.
- No scroll hijacking, forced horizontal scrolling, autoplay audio, or essential information inside WebGL.
- No public inventory of every homelab service.
- No publication of unreleased product names, private repository links, or identifying private-project metadata.
- No AI-generated decorative project imagery.
- No analytics SDK, tracking pixel, cookie, telemetry endpoint, WebGL renderer probing, Web Audio fingerprinting, or third-party beacon in the initial release.
3. Audience and information priorities
The primary reading path must answer these questions in order:
- Who is Luca and what kind of role fits him?
- What has he built and operated?
- Does he understand real systems, deployment, security, and maintenance?
- Can he build useful software across frontend, backend, mobile, data, and computer vision?
- How can someone contact him?
The first screen must communicate the name and hybrid role before the visitor interacts with the scene. Project descriptions favor the problem, Luca's responsibility, technical decisions, and current maturity over long feature lists.
Evidence balance
Before the Toolkit section, the static reading path presents two systems case studies and two primary software case studies with comparable heading level, narrative depth, and visual priority. The systems track comprises Professional systems operations within Experience and Secure self-hosted platform and lifecycle within Infrastructure. The software track leads with two Selected Builds; the remaining projects are visibly supporting evidence rather than peers of the two tracks. Systems claims emphasize verified operational work—ingress and TLS, identity and access, deployment lifecycle, and troubleshooting—rather than the number of installed services. Backup, recovery, monitoring, or automation claims appear only when the private editorial ledger contains verified evidence.
Audience acceptance
Before release, at least three independent reviewers representing hiring-screening and technical-interview perspectives complete a static or reduced-motion first pass. Within 30 seconds, each reviewer must identify Luca's name, equal hybrid role, and contact path. Within 60 seconds, each must identify at least one credible systems proof point and one credible software proof point. At least two of the three must rate the information layer as professional, readable, and not obscured by the scene, and rate the systems/software evidence balance at least 4 out of 5. Any failure triggers a content/hierarchy revision, not an instruction to add more visual effects.
4. Public identity and privacy rules
Canonical identity
- Public name: Luca Pîslaru.
- Public role: System Administrator & Full-Stack Developer.
- The exact diacritic-bearing name is used consistently in the page title, H1, metadata, JSON-LD, contact section, and social profiles where those profiles support it.
- A plain-ASCII name variant may appear only in structured alternate-name/search metadata when technically useful; it must not replace the visible canonical name.
Private projects
The medication product is labeled Private self-hosted medication tracker. The healthcare product is labeled Private healthcare platform. Neither receives a public repository or product link.
Unreleased or identifying names must not appear in:
- headings, descriptions, captions, alt text, or accessible names;
- image and video filenames delivered to the browser;
- EXIF or other embedded asset metadata;
- page source, comments, source maps, analytics labels, or JSON-LD;
- screenshots, browser chrome, logos, title screens, or visible application copy.
Private media uses unmistakably fictional identities and placeholder medication/health values generated without copying production data. Cropping or blurring is not the primary privacy control. No public asset may expose real, linkable, or derived personal/health information, email addresses, notifications, account identifiers, credentials, API URLs, hostnames, QR/barcodes, tokens, real internal topology, or recovery details. Clearly labeled fictional interface values permitted by the private ledger's synthetic schema are allowed.
The permitted health-demo schema uses labels such as Demo profile, Medication A, and Medication B; arbitrary non-real quantities/times; and no email, phone, birth date, address, diagnosis, real drug name, free-text note, or value copied from a production/user dataset. The interface or caption visibly identifies the data as fictional demonstration content.
Every image, chart, video, icon, font, and audio source passes a closed asset-clearance pipeline before entering public/ or a distributable source directory. Its asset record contains:
- a safe public asset ID and generated filename;
- source, owner, public-display permission, license, and attribution requirement;
- privacy classification and approval owner;
- confirmation of synthetic/demo data for private health interfaces;
- OCR and full-resolution manual-review results for images;
- representative frame sampling plus title/poster/end-frame review for video, with frame-by-frame review whenever identifiers can change during playback;
- metadata and unexpected-track stripping, safe-format transcoding, and external-reference checks;
- final output hash and approval date.
The private editorial/clearance ledger is a preparation input outside the public repository and outside all Vite input graphs. It contains source paths and fingerprints, evidence references, approver identities, private classifications, denylist material, and clearance details. The preparation pipeline validates this ledger and projects it through an explicit allowlist into exactly two public content artifacts:
- a typed
PortfolioContentroot containing approved display copy, identity, profile, experience, infrastructure evidence bands, projects, toolkit, contact email/social links, metadata copy, and safe asset IDs; - a public asset manifest containing only safe asset ID, generated filename, sanitized-output hash, approved public rights-holder/license/attribution text, media type, dimensions, and duration.
Contextual captions, alt text, long descriptions, and other rendered accessible copy exist only in PortfolioContent; the asset manifest never supplies contextual rendered wording. Neither public content artifact may contain private source paths or fingerprints, evidence IDs/locations, internal source-owner or approval-owner identity, approval workflow, privacy classification, denylist data, original filenames, source sizes, or rejected copy. Approved public rights-holder identity is permitted only inside the manifest's legally required attribution field and the generated distribution notices. Sanitized asset bytes form the separate non-authoritative PreparedAssetSet: every member is enumerated exactly once by manifest ID/filename/hash/type/dimensions, and preparation/build reject missing, extra, hash/type/dimension-mismatched, symlinked, or unmanifested files. Artifact tests reject both prohibited key names and known private values in all three prepared outputs and their compressed forms.
SVG is treated as active untrusted content: scripts, event handlers, foreignObject, embedded HTML, animation, and external URLs are removed through an allowlist sanitizer. Decorative SVG is served through <img> or rasterized when practical. Video and images are transcoded into known-safe formats and the final encoded artifact—not only the source—is inspected.
Private projects are pseudonymized before their content enters any repository checkout used for building. Development occurs in a private staging repository. Direct pushes to the public mirror are forbidden; only a trusted publisher may update it after the full publication gate below succeeds. A deployment-only, masked denylist covers known identifiers and aliases without being bundled or printed in CI logs. Privacy gates scan tracked paths and source, generated HTML/JavaScript/CSS, manifests, decoded source maps if generated, decompressed .gz/.br output, asset filenames, metadata, OCR output, and sampled video frames. Seeded canary fixtures must prove the gate fails for every supported leakage surface. Every externally reachable preview runs the same privacy gate.
The denylist is supplied to the scanner as a read-only secret mount or file descriptor, never a command-line argument or an environment value likely to appear in diagnostics. Rules have opaque IDs; failures report only rule ID plus file/frame coordinates, never matched text or decoded payload. Shell tracing, payload snippets, core dumps, persistent scanner caches, and payload-bearing crash reports are disabled. Canary inputs are generated ephemerally in isolated negative-test workspaces, must fail, and are discarded; production scanning has no fixture exclusions.
Dedicated offline QR and one-dimensional barcode detection/decoding runs on final images, posters, and applicable video frames. Detectable barcode geometry or a decodable payload fails clearance. Logs contain coordinates only. Ephemeral negative tests include payload-bearing QR and barcode canaries.
For every public-mirror publication—not only its initial creation—the trusted pipeline scans a complete non-shallow private-staging clone and every newly publishable commit, tree, blob, reachable ref/object, tag, LFS object, generated archive, and prepared artifact with the denylist, metadata, OCR, and QR/barcode gates. Only the exact closure and artifacts bound by the replay-safe signed release manifest may enter the public mirror/deployment; CI on an already-public push is not the primary privacy boundary. Any finding blocks publication. If private material ever reaches a public remote, the response is to revoke/rotate exposed credentials or identifiers where applicable, remove affected release assets and caches, perform a verified history rewrite or clean export, contact the hosting provider about retained artifacts, document potentially surviving forks/clones, and re-run the complete gate; deletion in a later commit is not remediation.
Every MIME-detected container in Git, LFS, release archives, dependencies, and prepared artifacts is inspected recursively, including ZIP/7z/tar and compressed variants, OOXML/OpenDocument, JAR/APK, and any nested combination. Extraction is networkless and never follows symlinks, absolute paths, .. traversal, device nodes, or external relationships. Encrypted, password-protected, unsupported, malformed, or policy-unknown containers fail closed. Limits are maximum depth 3, 10,000 members, 1 GiB aggregate expanded bytes, 100:1 expansion ratio per layer, 512 MiB per member, and five minutes per container; exceeding any limit rejects the input rather than partially scanning it. Every extracted member receives the same denylist, secret, metadata, OCR, QR/barcode, and applicable media gates. Unnecessary opaque binaries are prohibited from the public mirror. Negative fixtures cover nested and encrypted archives, archive bombs, OOXML external relationships/macros, traversal/symlink entries, and LFS-hosted containers.
Private evidence and received-source registers
Source fingerprints, byte sizes, original filenames, resolver paths, evidence-to-claim mappings, and category-revealing source inventories remain exclusively in the external private ledger. The public specification and repository contain only opaque public record IDs and approved sanitized-output hashes. The private register covers every received document/media source plus factual sources for:
- canonical identity, approved contact fields, and every optional hiring-screening field;
- every experience and education entry and each Professional systems operations claim;
- each of the four Infrastructure evidence bands and every operational example;
- each primary/supporting project fact, maturity statement, contribution, and approved public URL or private/no-link state;
- every Toolkit technology claim and its evidence category;
- every asset's ownership, display right, license, clearance, and derivative chain.
Each private factual source record has an opaque evidence ID, source class, immutable fingerprint, as-of date, resolver, owner, and rights/privacy status. Each private editorial record references one or more evidence IDs and a stable opaque public record ID. Evidence IDs, fingerprints, and mappings are consumed only by private preparation and are never projected into PortfolioContent, the public manifest, logs, attestations, or repository history.
Approval is an append-only signed envelope, not a mutable status field. Every emitted public record—including factual, editorial, profile, caption, accessibility, metadata, contact, toolkit, and asset-manifest records—requires exactly one current valid approval for its complete payload. All JSON digests below use J(schema, value) = SHA256(UTF8(RFC8785({schema, value}))), represented as exactly 64 lowercase hexadecimal characters; raw-file digests use B(bytes) = SHA256(bytes) in the same representation. Strings must be valid Unicode without unpaired surrogates; identifiers and paths are NFC-normalized before validation, and a non-NFC input is rejected rather than silently rewritten.
Each content approval binds approver key/authorized role, evidence fingerprints, typed public record ID, and approvedPublicRecordHash = J('portfolio-public-record/v1', completeProjectedRecord), including every string, maturity/contribution/outcome field, link-versus-private state, and referenced asset ID. Each asset approval binds approvedManifestRecordHash = J('portfolio-asset-manifest-record/v1', completeManifestRecord) plus sanitizedOutputHash = B(exactSanitizedBytes). The signed payload is {schema:'portfolio-approval-payload/v1', keyId, issuerEpoch, authorizedRole, evidenceFingerprints, recordClass, recordType, publicRecordIdOrAssetId, approvedPublicRecordHashOrManifestRecordHash, sanitizedOutputHashOrNull, decision, issuedAt, expiresAt, previousLedgerHeadHash, ledgerRevision, policyVersion}. Its Ed25519 signature is encoded as unpadded base64url. The complete envelope is {schema:'portfolio-approval-envelope/v1', payload, signature:{algorithm:'Ed25519', encoding:'base64url-nopad', value}}; the signature covers UTF8(RFC8785(payload)), and approvalEnvelopeDigest = J('portfolio-approval-envelope-digest/v1', completeEnvelope). Every field is mandatory except the explicitly typed null asset/content alternatives; unknown fields, alternate encodings, duplicate JSON keys, non-UTC RFC 3339 timestamps, and non-canonical signatures are rejected. Source/editor credentials cannot access the approval-signing key; the signer runs in a separate authenticated step. A signed rejection cannot be overwritten; a later decision appends a linked envelope.
Protected live-ledger state stores latestLedgerHeadHash and latestLedgerRevision and advances them by atomic compare-and-swap on every appended approval, rejection, revocation, or expiry-superseding envelope—not only on publication. Preparation requires exact equality with that live head/revision and recomputes every canonical record/output hash. Any ledger append immediately invalidates in-flight preparation/release candidates. Release expiry may never exceed the earliest current approval expiry. Every attestation, signature, transaction admission, recovery attempt, readiness check, and final visibility commit uses the protected control-plane clock and requires now < each bound approval, projection-attestation, workload-attestation, candidate, and release-manifest expiry; time expiry needs no ledger append to invalidate the transaction.
Approval closure encoding is exact. Reject duplicate, missing, or extra record/asset IDs. Sort content tuples by UTF-8 byte order of (recordType, publicRecordId) and asset tuples by UTF-8 byte order of assetId. Compute approvedRecordRoot = J('portfolio-record-closure/v1', {records:[[recordType,publicRecordId,approvedPublicRecordHash,approvalEnvelopeDigest], ...]}) and approvedAssetRoot = J('portfolio-asset-closure/v1', {assets:[[assetId,approvedManifestRecordHash,sanitizedOutputHash,approvalEnvelopeDigest], ...]}). The complete proof list contains [recordClass, recordTypeOrEmptyString, publicRecordIdOrAssetId, approvalEnvelopeDigest] for every tuple, sorted by UTF-8 byte order over the first three fields, with content before assets only where those fields differ naturally; approvalProofSetDigest = J('portfolio-approval-proof-set/v1', {envelopes: completeProofList}). Record count and typed tuple boundaries are therefore canonical rather than delimiter-dependent.
PreparedAssetSet is not hashed as an implementation-dependent directory. Reject directories, symlinks, hard-link aliases, backslashes, absolute paths, dot segments, case-fold collisions, duplicate IDs/paths, and extra files. Sort members by UTF-8 byte order of (assetId, publicPath) and compute preparedAssetSetDigest = J('portfolio-prepared-asset-set/v1', {members:[[assetId, publicPath, mediaType, widthOrNull, heightOrNull, durationMsOrNull, B(exactMemberBytes)], ...]}); the complete set must equal the public manifest one-for-one. Compute portfolioContentDigest = J('portfolio-content/v1', PortfolioContent), publicAssetManifestDigest = J('portfolio-public-asset-manifest/v1', publicAssetManifest), and siteConfigDigest = J('portfolio-site-config/v1', siteConfig). The fixed-order four-input closure is productionInputRoot = J('portfolio-production-input-root/v1', {inputs:[['PortfolioContent',portfolioContentDigest],['PublicAssetManifest',publicAssetManifestDigest],['PreparedAssetSet',preparedAssetSetDigest],['SiteConfig',siteConfigDigest]]}); no alias, omitted input, or additional mutable input is permitted.
The preparation gate computes a closed coverage matrix. It fails when any required public-record class above is absent; any emitted content or manifest record lacks exactly one current valid approval for its exact canonical payload hash; a reference is missing, stale, unauthorized, expired, revoked, rolled back, duplicate, extra, or hash-mismatched; an asset lacks an approved derivative; a public URL has not been independently verified; or an unconsumed private source remains marked required. The gate also enforces exactly one public owner for all contextual rendered/accessibility copy: PortfolioContent. Only after that private completeness check succeeds may the public projection and PreparedAssetSet be generated. Publication of any derivative remains blocked until its private record is cleared and its sanitized output hash is present in the signed approval, approvedAssetRoot, and public asset manifest.
The medication tracker and private healthcare media require independent manual approval after sanitization. The private game prototype uses gameplay footage only; its identifying title screen is excluded.
Contact privacy
Email is the primary action. It is an ordinary mailto: link with a visible text email fallback and a URL-encoded subject such as “Portfolio inquiry.” It works without JavaScript and never depends on a contact-form backend. GitHub, GitLab, and LinkedIn are secondary actions with icons and visible labels. External profile links use HTTPS, exact approved hosts, and rel="me noopener noreferrer" when opened in a new tab. There is no CV download. The contact section may state: “For a current CV or role-specific information, contact me directly.”
Canonical domain and contact email are required deployment inputs. Each social URL is independently optional. Missing social profiles are omitted from both visible links and JSON-LD rather than rendered as placeholders or dead links.
5. Journey and page structure
The pre-rendered single-page document uses native scrolling and semantic section anchors. The background road persists throughout the entire page while content panels enter and leave over it.
00 — Start
- H1: Luca Pîslaru
- Immediately adjacent role subtitle: System Administrator & Full-Stack Developer
- A concise value proposition focused on building and operating reliable systems and software.
- Primary experiential control: START THE DRIVE
- Supporting text: Enables the interactive soundtrack.
- A conventional “Explore work” anchor remains available independently of audio.
The car and environment already cruise silently. Starting the drive unlocks the generated soundtrack and richer feedback but does not unlock or gate content.
01 — Profile
A short professional introduction explains the equal systems/software hybrid. It should establish comfort with Linux, infrastructure, automation, backend and frontend delivery, and learning through building. The copy must be plain and credible, without “passionate ninja,” “digital craftsman,” or similar portfolio clichés.
Because there is no public CV download, the profile and experience sections provide the approved minimum hiring-screening set: current city/country or remote availability if Luca elects to publish it, education, relevant employment, languages, and work-preference information that Luca has explicitly approved. Citizenship, work authorization, phone number, street address, birth date, personal identifiers, and any unapproved screening detail remain private. A print stylesheet produces a clean printable portfolio view but does not label or package it as a résumé download.
02 — Experience
Show a concise reverse-chronological narrative derived from approved experience evidence. Each entry contains role, organization, dates in MMM YYYY – MMM YYYY format (or MMM YYYY – Present), location/remote status where approved, and two to four outcome-oriented points. Overlapping roles remain separate and preserve their actual dates. Copy must stay faithful to verified evidence and must not invent quantified impact.
The Professional systems operations case study is composed only from verified systems-administration responsibilities and outcomes in the experience records. It receives its own visible subheading and summary rather than being buried inside a generic timeline. If the private ledger cannot substantiate a proposed operational claim, the claim is omitted rather than replaced with a homelab claim.
Authoritative content register
PortfolioContent is the single public subject-matter source for identity, profile, hiring-screening fields, experience, professional systems operations, infrastructure evidence bands, projects, toolkit, contact email/social URLs, metadata copy, social-preview asset, captions, contextual alt text/long descriptions, and safe asset references. Vue components supply no independent subject-matter string. The only other structured public strings are the asset manifest's approved legal attribution/license text and siteConfig deployment URL/robots values, confined to the exact surfaces defined in §11.
The private editorial ledger holds the approval/evidence form of those records. Each record includes a stable opaque public record ID; one or more private evidence IDs; as-of date; Luca's role/contribution; problem; technical decisions; outcome; maturity; verified public URL or private/no-link state; referenced asset IDs; and factual, privacy, and licensing approval. The preparation pipeline validates the private form against the closed coverage matrix in §4, strips all governance/evidence fields, and generates PortfolioContent through the allowlist defined there.
The complete mutable production input set is exactly the generated PortfolioContent, public asset manifest, hash-bound PreparedAssetSet, and narrowly scoped siteConfig defined in §11. Application source and exact lockfile are versioned code inputs, not subject-matter authorities. No environment variable, component constant, file-system discovery, or other mutable input may influence subject-matter copy, legal attribution, deployment metadata, or asset selection. PortfolioContent owns subject-matter/rendered accessibility copy; the manifest owns only technical asset metadata and approved legal attribution; PreparedAssetSet contains non-authoritative bytes validated against the manifest; and siteConfig owns only the deployment surfaces named in §11. The build rejects missing/extra inputs, placeholder URLs, unrecognized maturity values, broken or unmanifested asset references, public links on private records, contextual rendered copy sourced from the manifest, or subject-matter text not reachable from PortfolioContent. Content changes require a new private preparation/approval date and regenerated public artifact hash; that date itself is not published unless explicitly approved as content.
03 — Infrastructure
Present the homelab as a compact systems case study, not a container inventory.
The diagram and supporting text show:
- a repurposed PC running Linux;
- Docker-hosted services;
- a personal domain and Proton Mail custom-domain email;
- Nginx on the host as the reverse-proxy entry point;
- Let's Encrypt certificates managed and renewed with Certbot;
- fail2ban jails protecting exposed entry points;
- Authelia in front of services that lack suitable native authentication, with passkeys, two-factor authentication, email recovery, and access policy;
- a curated service layer containing Nextcloud, SearXNG, Vaultwarden, and Gitea, with Pi-hole shown only as a smaller network-utility node rather than a headline service.
The public diagram excludes private, irrelevant, or potentially sensitive services. It never shows real hostnames, domain names, IP addresses/ranges, ports, usernames, service versions, recovery endpoints, exact fail2ban thresholds, or authentication-policy rules. The narrative emphasizes deployment, authentication, certificate lifecycle, reverse proxying, updates, service enrollment and retirement, and operational debugging.
The infrastructure case study is organized into four evidence bands:
- Ingress and TLS — domain routing, Nginx, Let's Encrypt, Certbot renewal, and fail2ban at a safe level of abstraction.
- Identity and access — Authelia, passkeys, two-factor authentication, recovery, and protected services without exposing real policy details.
- Service lifecycle — Docker deployment, updates, enrollment, retirement, and selected representative services.
- Operations — one or more verified troubleshooting/maintenance examples approved in the private editorial ledger and projected into
PortfolioContent. Backup, recovery, monitoring, or automation appears only if separately verified.
At least two of these bands are visible without opening an accordion or modal. The infrastructure section receives narrative and viewport weight comparable to one large software case study plus one supporting project card.
04 — Selected Builds
Use two primary software case-study panels followed by one visibly smaller supporting research panel:
-
Private self-hosted medication tracker
A multi-device medication system with profiles, scheduled and as-needed medication, stock tracking, adherence/logging, notifications, sync, a server component, and an administrative interface. Use sanitized mobile screenshots as the primary visual story. No product name or public link. -
Footy Tracker
A work-in-progress computer-vision pipeline for football footage, including player detection and tracking, with jersey recognition clearly described as ongoing work. Use the annotated match frame and, where useful, a short muted clip. Do not imply production readiness. -
Opinion Dynamics Simulation — supporting research panel
An experimental agent-based simulation. Use a considered grid of the supplied result charts, with one lead chart and smaller supporting views. Explain what the model explores and label it honestly as experimental work. Each chart group includes a visible caption and adjacent structured description covering its purpose, axes/variables, key trends, and conclusion; provide a data table when exact values are material to the claim.
05 — Additional Work
Use smaller but still substantive entries:
- Private game prototype — a three-week prototype represented by a short, optimized gameplay loop extracted from the gameplay portion of the supplied video. No title screen or public link. Publication requires confirmed rights to display every visual and audio element in the selected excerpt.
- Private healthcare platform — a private web platform presented generically with a sanitized interface screenshot and no public link.
- Currency Converter — a deliberately modest .NET/Avalonia learning project; concise description, public link if verified, and no attempt to inflate its scope.
- Linux Modding Guide — community documentation presented as evidence of technical writing and Linux troubleshooting. Its verified public repository is linked. Live popularity counts are omitted from the initial release.
06 — Toolkit
The toolkit is a restrained onboard diagnostic console, not a rating chart. Each tile contains the official technology icon and a visible text label. Tiles are grouped into two primary banks:
Systems & delivery
- Linux
- Docker
- Nginx
- Proxmox / KVM
- Git
Software & data
- Python
- Vue.js
- JavaScript
- C# / .NET
- Flutter / Dart
- PostgreSQL / SQL
- Headless WordPress
Java appears only in a smaller Additional experience group. There are no percentages, star ratings, years-of-experience badges, or “expert” labels.
07 — Destination / Contact
The environment reaches a restrained pre-dawn destination. The car slows to a confident cruise, route progress reaches 100%, and the HUD reads ARRIVED.
Visible copy:
07 / DESTINATIONCONTACT- END OF THIS ROAD.
- START OF THE NEXT.
- Luca Pîslaru
- System Administrator & Full-Stack Developer
- Primary CTA: START A CONVERSATION
- Supporting note: For a current CV or role-specific information, contact me directly.
- Secondary links: GitHub, GitLab, LinkedIn
The phrase is intentionally a little playful, but the surrounding presentation remains quiet and professional.
6. Visual direction
Two-layer design system
The site deliberately separates two visual layers:
- World layer: expressive retro-futuristic road, terrain, sun, car, haze, stars, signs, motion streaks, and generated audio.
- Information layer: crisp, modern, restrained panels with excellent readability and minimal decoration.
The world creates personality. The information layer must never look like a themed game menu.
Environment
- Deep navy-black sky.
- Large warm sun at the horizon.
- Cyan and magenta wireframe terrain used with restraint.
- Dark road, cyan edge lighting, and warm center markers.
- Sparse stars, atmospheric haze, and speed streaks that intensify with scroll velocity.
- Subtle CRT/grain treatment applied only to the environment, never to body text or content panels.
- The scene evolves slowly from deep night near the introduction toward restrained pre-dawn at Contact.
Section-specific silhouettes and atmospheric structures may appear in the distance. They are environmental storytelling, not literal floating technology logos.
Car
The car is an original, non-branded retro-futuristic grand tourer viewed from a rear chase perspective. It is a low, wide wedge in dark gunmetal or near-black, with a continuous red rear light and restrained cyan lighting or underglow. It must not reproduce a recognizable production model, manufacturer badge, or trademarked silhouette.
The car is the stable visual anchor. Its response to speed includes subtle suspension movement, lighting change, road spray/particles, and motion streaks. Camera shake remains minimal and disappears in reduced-motion and low-quality modes.
Content panels
- Near-black, mostly opaque surfaces.
- Crisp off-white text.
- Cyan for navigation, technical state, and route language.
- Amber for primary actions and destination emphasis.
- Minimal rounding and glow.
- Clear borders and strong spacing rather than glassmorphism.
- Desktop panels occupy roughly 40–45% of the viewport and alternate sides while preserving a recognizable road-and-car center.
Typography
- Modern geometric display sans for large headings.
- Neutral, highly readable sans for body copy.
- Restrained monospace only for route labels, HUD state, project metadata, and small technical annotations.
- Fonts are self-hosted when licensing permits. The initial render uses stable fallback metrics to prevent layout shift.
7. Motion and interaction model
Native scrolling
The browser owns scrolling. Scroll position selects the active section; scroll velocity produces temporary acceleration. The drive controller calculates velocity from position delta over time, applies clamping and exponential smoothing, and decays naturally toward cruise speed when scrolling stops.
Acceleration may influence:
- apparent road speed;
- controlled camera field of view;
- terrain and center-line flow;
- car suspension and lighting;
- particle/streak density;
- audio filter and engine intensity after audio is enabled.
It must not alter document distance, trap the user, or make precise navigation difficult.
Section signs
During continuous forward passive scrolling, an upcoming section boundary may receive a futuristic hover sign that:
- becomes visible near the horizon;
- approaches with the road;
- stabilizes briefly beside the car using small visual micro-thrusters;
- displays only the compact route label, such as
03 / INFRASTRUCTURE; - falls behind as the content panel settles into view.
Signs are deliberately forward-journey embellishments, not a second navigation system. They are suppressed during reverse scrolling, Home/End or multi-section jumps, explicit link navigation, initial-fragment/history restoration, and reduced/static motion. They do not carry prose. Their text is duplicated by real semantic headings, so signs are decorative and hidden from assistive technology.
Navigation and URL behavior
- A compact navigation control exposes native links to every section.
- Explicit keyboard or pointer activation to a different canonical fragment creates one history entry, scrolls to the semantic section, and then focuses its heading with
tabindex="-1"after scrolling settles without causing a second scroll. Activation of the already-current fragment creates no entry but still aligns and focuses the heading. - Passive scrolling may update the current fragment with
replaceStateafter the section is stable for 150 ms; it never creates a history entry and never moves focus. - Intersection observers, resize observers, scene state, and scroll position never move focus.
- Browser back/forward navigation restores the corresponding section without pushing or replacing another entry and without programmatically moving document focus.
- Direct fragment URLs load at the correct semantic section even if WebGL is unavailable.
- Motion pause, sound, and quality controls are always reachable without opening the main navigation.
The single active-section rule is: select the last section heading whose top edge is at or above an activation line at 35% of the visual viewport height. Before any heading crosses the line, select the first section; when the document reaches its maximum scroll position within two CSS pixels, select Contact. Heading offsets are recalculated after document.fonts.ready, asset dimension changes, ResizeObserver notifications, orientation changes, and visual-viewport changes. At identical positions, document order wins. The same active-section ID drives the real navigation state, HUD, environment chapter, and route state. The decorative sign uses the separately latched transition target defined in §12 and is not another source of semantic section truth.
An internal source flag (initial, explicit-navigation, passive-scroll, or history-restoration) and monotonic navigation epoch prevent scroll/URL/focus feedback loops. Every explicit navigation, popstate/hash restoration, wheel/touch scroll intent, Page Up/Down, Home/End, Space, or arrow-key scroll intent increments the epoch and cancels older settle, focus, and replaceState jobs.
With JavaScript, a same-document navigation link prevents the native default only after confirming a valid target. It increments the epoch and compares the exact decoded target section ID with the canonical current fragment ID; an empty fragment canonicalizes to the Start section, and any non-canonical/unknown fragment is invalid. If the IDs differ it calls pushState exactly once with the canonical #id; if they match it performs no history mutation. It then scrolls to the target in either case. Scroll settlement uses native scrollend when available; the fallback requires three consecutive animation frames with absolute scroll delta <1 CSS pixel. After 1500 ms without settlement, it performs one instant final alignment. Heading focus occurs on the next frame only if epoch, source, and destination still match and no intervening user scroll intent occurred. Without JavaScript, the unchanged href provides native anchor behavior.
Passive fragment replacement captures the current epoch and section ID, waits for 150 ms of stable active-section state, and executes only if both still match. popstate increments the epoch, cancels pending work, performs restoration without another history mutation, and never moves focus. Direct initial fragments, passive scrolling, and history restoration never steal focus. Only a still-current explicit in-page navigation moves focus.
8. Audio design
Audio never starts automatically. The page initially runs silently and visibly advertises the optional experience through START THE DRIVE and the line Enables the interactive soundtrack.
On explicit activation:
- the Web Audio context starts;
- a short ignition transition plays;
- a generated, original ambient drive soundtrack fades in;
- the primary control becomes compact sound and volume controls;
- scroll velocity changes engine intensity, filtering, and environmental texture without making the music frantic.
Audio is synthesized or built from original/licensed material; no reference-site track or copied recording is used. Mute, volume, and motion are separate preferences. A remembered preference may restore control state, but a returning visitor still explicitly resumes audio in the new browsing session.
Audio keeps separate actualState, desiredState, and suspensionReason. Actual states and legal edges are:
idle → starting | closed;starting → running | suspended | failed | closed;running → suspended | failed | closed;suspended → running | failed | closed;failed → closed;closedis terminal.
Desired state is idle before activation, then one of running, suspended, or closed. Browser interrupted is normalized to actual suspended with suspensionReason='interruption'; it is not a second ambiguous actual state. failed is terminal for the session and is selected only when initial context/graph creation or first explicit start fails, the graph becomes invalid/a node cannot be recreated, or safe silence cannot be guaranteed after a suspend failure. Start is idempotent: repeated or rapid activation creates at most one live AudioContext and graph. Muting or changing volume while starting updates the pending target deterministically. A rejected initial start shows Audio unavailable without affecting content.
All Web Audio operations run through one serialized reconciler with a monotonic operation generation. The graph is built behind a zero-gain, disconnected master output and connects/audibly ramps only after the latest generation still desires running. After every awaited initialization, resume(), suspend(), or close(), reconciliation checks generation, visibility, page lifecycle, activation, mute/volume, actual state, and latest desired state. A completion superseded by closed disconnects and closes anything it created exactly once. A completion superseded by suspended may retain the one graph only after that same context successfully suspends; it never audibly attaches first. No stale completion updates controls or restarts sound.
The controller also stores explicitlyActivated and resumeIntent (none | automatic-after-visibility | user-required). This table is exhaustive; failed and closed rows override every other trigger:
| Trigger and source condition | Required desired/actual result |
|---|---|
Hidden/visible change or persisted pagehide/pageshow before activation (idle) |
remain desired/actual idle; create no context/graph |
Visible Start activation from idle |
set explicitlyActivated=true, desired running, resumeIntent=none; enter starting, then running or failed |
Normal hide or persisted pagehide while starting or running |
set desired suspended, resumeIntent=automatic-after-visibility; starting → suspended only after safe initialization/suspend, or running → suspended |
Normal visible visibilitychange or matching pageshow while actual is still starting with automatic resume intent |
set latest desired state back to running; retain the same serialized initialization generation; connect/ramp only after current-generation initialization succeeds and visibility is rechecked |
Normal hide or persisted pagehide while already suspended for visibility |
remain suspended and preserve automatic resume intent |
Normal hide or persisted pagehide while suspended for browser interruption/user request |
remain suspended with resumeIntent=user-required; visibility must not convert it to automatic |
Normal visible visibilitychange or matching persisted pageshow with intact graph and automatic resume intent |
set desired running, clear intent after success, run serialized resume; rejection remains suspended and changes intent to user-required with Resume sound |
Normal visible visibilitychange or pageshow with resumeIntent=user-required |
no-op; remain suspended until explicit Resume sound |
Browser interruption while starting |
set desired suspended, reason interruption, resumeIntent=user-required; current initialization may complete only into safely suspended state |
Browser interruption while running |
normalize to actual/desired suspended, reason interruption, resumeIntent=user-required; show Resume sound |
User activates Resume sound from resumable suspended |
desired running; success enters running, rejection remains suspended/user-required; never create a second graph |
Mute/volume change in starting, running, or suspended |
update target gain only; do not change actual/desired lifecycle state or resume intent |
Any visibility/page event while failed |
remain actual failed; desired lifecycle requests are ignored until final close |
Any event while closed |
remain terminal; no operation or graph creation |
| Non-persisted pagehide, unmount, or final teardown from any non-closed state | desired closed; legal idle/starting/running/suspended/failed → closed; invalidate and tear down exactly once |
If a hide/pagehide-triggered suspend() rejects, the controller synchronously sets master gain to zero and disconnects it from destination, then closes the graph exactly once, enters failed, and shows Audio unavailable when visible. At no point may a suspend failure leave audible output. Unsupported or blocked audio is non-blocking for the portfolio, but every lifecycle fault oracle must still pass.
9. Responsive behavior
Desktop and wide screens
- Full chase-view composition.
- Alternating 40–45% content panels.
- Richest terrain, particles, atmospheric structures, and sign approach.
- The car and road remain legible at the center of the composition.
Tablet
- Reduced camera movement and particle budget.
- Slightly smaller car and more centered content geometry.
- Panels may widen and alternate less aggressively.
- Hover signs use a shorter approach and stabilization sequence.
Mobile portrait
- A recognizable but simplified road, sun, and smaller chase-view car remain visible.
- Content panels become almost full-width, highly opaque reading surfaces.
- Signs become compact HUD banners that dock briefly rather than competing for narrow horizontal space.
- Camera shake is removed, particles are reduced, and expensive atmospheric passes are disabled.
- Touch targets are at least 44 by 44 CSS pixels.
- No carousel is used for projects or toolkit items; content wraps in normal document flow.
Reduced motion and static mode
When prefers-reduced-motion is active at initial load, Three.js, animated project media, and the WebGL context are not downloaded or initialized. The page uses the static composed poster, instant section-state changes with non-moving emphasis such as color or border changes, no speed streaks, and no camera shake. A runtime system change or manual pause cancels the animation loop and decorative media within one animation frame. Audio remains independently controllable.
Preference precedence is fixed:
- repeated WebGL failure or explicit static mode;
- current system
prefers-reduced-motion: reduce; - manual Pause motion;
- saved quality preference;
- adaptive-quality decision.
A saved full-motion or quality preference never overrides a current system reduced-motion preference. Resuming motion is unavailable while the system preference requests reduction; the control explains why without using a live-region announcement.
Motion/resource transitions are normative:
| Trigger | From | Result and resource behavior |
|---|---|---|
| Initial system reduction, saved pause, or saved Static | idle |
Enter poster-backed paused/static; do not request Three.js, live assets, or video sources |
| System changes to reduce | loading, running, paused, or lost |
Invalidate generation, abort loads/restoration, dispose partial/live GPU resources, detach automatic video sources, enter static |
| System later stops reducing | static |
Remain static; show Enable motion and reinitialize only after explicit activation |
| Manual Pause | running |
Enter paused, stop RAF within one frame, retain the complete GPU set and last rendered canvas frame, stop/detach automatic video |
| Manual Pause | idle or loading |
Invalidate/abort and dispose partial work, show poster, enter paused |
| Manual Pause | lost/restoring |
Cancel restoration, dispose the lost generation, show poster, enter paused |
| Manual Resume | paused |
If a complete valid GPU generation was retained, resume running; otherwise enter a fresh loading generation |
| Explicit Static quality | any non-disposed state | Invalidate/abort, dispose live resources, detach automatic video, show poster, enter static |
| Explicit higher quality | static with no system reduction |
Enter a fresh loading generation only after Enable motion activation |
User-requested playback of an individual project video is independent from ambient motion. In reduced/static/data-saver states it attaches only that video's source after Play, never initializes Three.js, and detaches again when the video leaves the viewport or the visitor stops it.
10. Accessibility requirements
Target WCAG 2.2 AA.
- A skip link moves directly to the portfolio content.
- Semantic landmarks, one H1, ordered headings, lists, buttons, and native links provide the page structure.
- All functionality is keyboard-operable with visible focus and no keyboard traps.
- Only a still-current explicit in-page section-link activation moves focus to the relevant heading, exactly as defined by the navigation epoch contract; passive scroll, direct initial fragments, and history restoration never move it.
- Canvas and decorative signs are hidden from the accessibility tree.
- One concise accessible description explains the visual metaphor: a retro-futuristic road journey that reacts to scrolling and marks progress through the portfolio.
- Screen readers receive normal portfolio sections, not live speed, engine, sign, or particle announcements.
- Informative project images have concise descriptive alt text; decorative crops use empty alt text.
- No video autoplays with sound. A muted loop may autoplay only when full motion is allowed, data saver is off, it is within its activation boundary, and it has an author-owned visible keyboard-operable play/pause control. The portfolio does not rely on inaccessible user-agent shadow-DOM media controls; all exposed media actions are authored, semantically named, stateful, and meet the target-size gate. Any automatically started motion lasting more than five seconds can be stopped. Reduced-motion mode shows a poster until explicit play.
- Video includes a caption or structured visual description appropriate to its content. Offscreen video pauses and stops decoding; failure leaves its poster and accessible explanatory text.
- The interface supports reflow at 320 CSS pixels equivalent and 400% zoom without content loss, and remains usable with the WCAG text-spacing overrides.
- Color is never the sole indicator of state; contrast meets AA requirements.
- Repeated technology icons are hidden from screen readers when the visible label already names the technology.
- Audio has an immediately available mute control after activation and never interferes with assistive-technology speech by default.
- Fixed HUD and control surfaces never obscure focused content. Forced-colors mode retains visible text, focus, and controls.
- No scene or media state exceeds the WCAG three-flashes-or-below-threshold requirement; high-speed and final encoded media states receive automated flash analysis plus manual review.
- All author-owned pointer/touch controls at every supported viewport target at least 44 by 44 CSS pixels. The only permitted target-size exception is an inline text link within a sentence/paragraph, marked and validated exactly as defined by the geometric oracle.
11. Technical architecture
Stack
- Vue 3
- TypeScript
- Vite
- Vue's official
vue/server-rendererpackage - Three.js, with custom shaders limited to the procedural road, terrain, sun, haze, and related environmental effects
- Web Audio API
- An in-repository build-time pre-render step that emits complete single-page HTML, then hydrates it in the browser
There is no Vue Router. Native section anchors and browser history are sufficient for this single document.
Exact pre-render and build contract
The project uses Vite's documented SSR build flow rather than a client-only shell or an additional application framework:
src/app.tsexports a universalcreateApp()built withcreateSSRApp()and contains no browser-only side effects during server rendering.src/entry-client.tscreates the same app and hydrates the existing#appmarkup.src/entry-server.tscreates a fresh app per render and calls Vue'srenderToString().- The client build emits hashed assets plus the Vite SSR manifest.
- The server build emits an importable server-render entry.
- An in-repository Node ESM script,
scripts/prerender.mjs, imports the server entry, renders the single/route, injects the result and preload links into the built HTML template, and writes the final staticdist/index.html. - The same script emits
sitemap.xml, environment-appropriaterobots.txt, validated JSON-LD, Open Graph metadata, and the static-host header/redirect examples required by the hosting contract.
The production build fails if the raw final HTML does not contain the canonical H1, all eight section headings, infrastructure text, project descriptions, toolkit labels, and contact link before any client script runs. Server and client receive the same immutable content/config snapshot to prevent hydration mismatch. Browser-only scene, audio, media-query, storage, and measurement behavior begins only in mounted client hooks.
Build-time configuration
A typed deployment-only siteConfig is validated by an in-repository strict parser before rendering. Unknown fields are rejected. Its only fields are environment, absolute HTTPS canonicalUrl, and immutable buildId. environment may influence only robots/noindex behavior and preview-versus-production header templates; canonicalUrl may influence only canonical/OG URL fields, sitemap locations, preferred-host redirects, and absolute URL resolution; buildId may influence only cache/version labels, the release manifest, and non-user-visible diagnostics. None may supply identity, role, locale, contact/social values, prose, captions, accessibility text, or asset attribution. Those derive exclusively from PortfolioContent or, for public rights-holder/license notices only, the asset manifest.
Validation rules include:
- production canonical URL must be HTTPS, contain no credentials/query/fragment, and use the approved host;
- the public content email must be a single valid public mailbox and is emitted only through a safely encoded
mailto:link and visible text; - public content social links must be HTTPS and match the exact approved GitHub, GitLab, or LinkedIn host for their field;
- protocol-relative,
javascript:,data:, control-character, redirector, and userinfo-bearing values are rejected; - JSON-LD is created with a serializer that escapes
<and script-closing sequences; - inline JSON-LD is covered by a build-generated CSP hash;
- production artifacts are host-specific because canonical URL, sitemap, robots directives, and metadata are embedded at build time, while the source remains portable between static hosts.
The build cross-validates every public asset ID against the public asset manifest, derives visible identity and structured metadata from the same PortfolioContent fields, and asserts equality among H1, page title inputs, JSON-LD identity, Contact identity, and visible contact link. The Vite graph cannot import the private ledger, denylist, or source resolver.
Layer boundaries
Semantic application layer
- Owns all portfolio copy, headings, links, controls, project media, metadata, and accessible behavior.
- Renders useful HTML before Three.js loads.
- Uses
PortfolioContentfor all subject-matter/rendered accessibility copy,siteConfigonly for deployment URL/robots surfaces, the manifest only for technical asset resolution/legal attribution, and hash-verifiedPreparedAssetSetbytes as non-authoritative payloads.
Journey coordination layer
useScrollDriveconverts native scroll input into normalized velocity and cruise/acceleration state.useJourneySectionsmaps section positions to active section, route progress, sign cues, and environmental chapter.useAudioEngineexposes explicit start, mute, volume, intensity, suspend, and teardown controls.useMotionPreferencescombines system preference and visitor override.useAdaptiveQualityselects and adjusts high, medium, low, or static quality.useKeyboardNavigationhandles predictable focus behavior for section navigation without replacing native link semantics.
Scene layer
- Ordinary TypeScript modules own renderer setup, camera, road, terrain, sun, car, signs, particles, post-processing, and lifecycle.
- The scene consumes a small serializable state object from the journey layer; it does not read the DOM or own portfolio content.
- Vue owns the canvas host and controls, not individual Three.js objects.
The scene lifecycle uses separate states and this transition graph:
idle → loading | paused | static | disposedloading → running | paused | lost | static | disposedrunning → paused | lost | static | disposedpaused → running | loading | lost | static | disposed;paused → lostis legal only when a complete retained generation still owns a live contextlost → restoring | paused | static | disposedrestoring → running | paused | static | disposedstatic → loading | disposed, whereloadingrequires explicit Enable motion and no current system reductiondisposedis terminal
Every dynamic import and asset load receives an abort signal plus an initialization-generation token. Every asynchronous completion checks the token and current state before attaching. A stale generation disposes its local result immediately and cannot alter canvas, controls, or state. There is exactly one canvas and one animation loop.
Transitioning to static or disposed cancels animation frames, loaders, observers, listeners, timers, and pending initialization, then disposes geometries, materials, textures, render targets, post-processing passes, and renderer resources exactly once. A hidden page pauses rendering and excludes hidden frames from quality measurements.
On webglcontextlost, including during loading or paused with a retained context, the handler calls preventDefault() to allow browser restoration, stops rendering immediately, records a monotonic lostAt, enters lost, aborts any loading generation, invalidates the GPU generation, and disposes partial/invalid handles exactly once before any rebuilt generation attaches. A paused state with no retained context cannot receive/transition on context loss. The logical restore cutoff is lostAt + 5000 ms. A visible-page watchdog requests evaluation at the cutoff, but timer delivery itself is not treated as authoritative while a page is hidden or frozen. Every restoration completion and every visibility/page lifecycle task rechecks performance.now() against the cutoff before attaching.
webglcontextrestored while hidden records restorationPending but does not rebuild. On the first subsequent lifecycle task, a pending restoration enters restoring only when the document is visible and performance.now() ≤ lostAt + 5000; otherwise it enters static. A rebuild that began before the cutoff may attach only after rechecking that its generation is current and performance.now() ≤ lostAt + 5000; a late completion is disposed and enters static. Rebuild failure or any later context loss also enters static for the session. The implementation never uses WEBGL_lose_context outside explicit test-only hooks.
Scene state is combined with a separate page-lifecycle overlay: active | frozen | disposed. No import/load/rebuild completion may attach unless the overlay is active, its generation is current, and its scene-state edge is legal. pagehide.persisted=true changes the overlay to frozen and applies this exhaustive table; no frozen row creates work:
| Scene state at persisted pagehide | Frozen action | Matching visible pageshow when motion is permitted |
|---|---|---|
idle |
retain idle; no resources | remain idle until normal demand |
loading |
abort generation, dispose partial resources, enter paused with resumeNeedsLoad=true |
enter one fresh loading generation |
running |
stop RAF, retain complete valid generation, enter paused with resumeNeedsLoad=false |
resume that generation and one RAF loop |
paused |
retain a complete generation when present; otherwise retain resumeNeedsLoad |
resume running or fresh loading according to that flag |
lost |
retain lostAt/logical cutoff and restoration-pending fact; no rebuild |
enter restoring only if before cutoff, otherwise static |
restoring |
abort/dispose partial rebuild, return to lost with same cutoff and pending restoration |
same lost rule above |
static |
retain poster/static state | remain static until explicit Enable motion |
disposed |
no-op | remains terminal |
If pageshow occurs while motion is disallowed, the motion-precedence table wins and no live generation starts. Non-persisted pagehide, Vue unmount, and final teardown set the overlay and scene to disposed, abort all work, release all resources/listeners/observers, and invoke audio's separate closed transition exactly once. No pageshow or late completion may attach a second canvas, loop, generation, or audio graph.
Audio layer
- An ordinary TypeScript engine owns Web Audio nodes and synthesis.
- It receives start/stop/volume/intensity values from
useAudioEngine. - It creates no context before explicit visitor activation.
- It follows the idempotent lifecycle and interruption behavior defined in the Audio section and exposes state without leaking the
AudioContextto Vue components.
Primary components
AppShell— landmarks, navigation, controls, and section composition.SceneCanvas— canvas host, poster fallback, lifecycle boundary, and accessible scene description.JourneyHud— route progress, current section, quality/motion state, and arrival state.DriveControls— Start the Drive, mute, volume, pause motion, and quality fallback.PortfolioSection— shared semantic section shell.ProjectCaseStudyandProjectCard— selected and additional work presentations.InfrastructureDiagram— responsive semantic SVG/HTML diagram with a text equivalent.ToolkitGrid— grouped icon/name tiles.ContactDestination— destination copy and contact actions.
No component may require the canvas to convey its meaning.
12. Data flow and state
- Native scroll and resize events are sampled through animation-frame scheduling.
useScrollDriveoutputs smoothed speed and transient acceleration, clamps invalid/negative elapsed time, resets transient velocity after hidden-page gaps, and handles upward scrolling and zero scroll range.- Measured heading positions and the 35%-viewport activation line determine the active section; intersection observers may schedule measurement but are not an independent source of truth.
useJourneySectionsemits the active chapter, sign transition, environment target, and destination state.- A small scene-state adapter passes normalized values to the Three.js engine each frame.
- When enabled, the audio engine receives a slower-smoothed intensity value to avoid harsh sound changes.
- HUD and navigation read the same journey state, keeping visual progress and semantic section state consistent.
Persistent preferences are limited to non-sensitive settings such as manual motion pause, maximum quality choice, and volume. They never store browsing history, section visits, GPU identity, audio characteristics, or contact actions. The initial release contains no behavioral analytics or telemetry. Adaptive quality uses ephemeral coarse frame-time samples only and does not export them.
Normative controller formulas
For scroll drive, sample scrollY with monotonic performance.now() in animation-frame work scheduled from passive scroll events. If dt ≤0, inputs are non-finite, or the document has no scroll range, emit cruise state and do not integrate. If dt >250 ms, treat it as a background gap: reset the transient component to zero and establish a new baseline. Otherwise:
raw = abs(deltaY) / dtin CSS pixels per millisecond;impulse = clamp(raw / 2.5, 0, 1);alpha = 1 - exp(-dt / tau), withtau=90 mswhile impulse is above the current smoothed value andtau=420 mswhile decaying;smoothed = smoothed + (impulse - smoothed) × alpha;driveSpeed = 0.18 + 0.82 × smoothed, clamped to[0.18, 1].
Upward and downward scroll use absolute velocity so either direction produces a short acceleration response; document position, not drive speed, determines route direction and section state. Unit tests use these constants, with no device-specific retuning.
Route progress is clamp(scrollY / max(1, scrollHeight - visualViewportHeight), 0, 1) and is zero when scroll range is zero. The final two-CSS-pixel rule may force exactly 1 only at document end.
Sign animation is eligible only while the source is passive-scroll, the latest non-zero sampled document delta is positive (forward/downward), and that delta is no greater than 0.75vh. Reverse/zero-direction input, explicit/history navigation, Home/End, a larger discontinuous jump, or crossing more than one activation boundary clears the latch and suppresses signs until a later eligible forward sample. Thus direct jumps have a deterministic no-sign result rather than synthesizing missed roadside objects.
For an eligible sign candidate, let d be that heading's document top minus the activation-line document position and vh the current visual viewport height. When no sign is latched, the candidate is the first section after the current active section. If a sample moves d from above 1.2vh to any value in (-0.25vh, 1.2vh], or the first eligible sample already lies in that interval, its section ID latches as signTargetId; skipped approach/stabilized phases resolve immediately from the current d. A sample that jumps directly to d ≤-0.25vh does not latch. Once latched, the target is retained until the pass completes even if that heading becomes the active semantic section. Its deterministic phase is:
- hidden when
d >1.2vh; - approach for
1.2vh ≥ d >0.55vh, mapped linearly from 0 to 1; - stabilized for
0.55vh ≥ d >0.15vh; - pass for
0.15vh ≥ d >-0.25vh, mapped linearly from 0 to 1; - hidden/complete when
d ≤-0.25vh.
Only the one latched signTargetId may be visible. During the pass phase, signTargetId may intentionally equal the active section ID; the sign does not switch early to the following section. At d ≤-0.25vh, the latch clears. On the next eligible forward passive sample, a new candidate may be selected from the section after the then-current active section. Any reverse direction clears immediately; reverse traversal intentionally shows no hover sign. Reduced-motion/static mode likewise has no sign latch or animated sign and changes the semantic/HUD section label only at the active-heading threshold.
13. Progressive loading and resilience
Load in this order:
- pre-rendered semantic HTML and critical CSS;
- static scene poster and stable layout dimensions;
- Vue interaction layer;
- separate Three.js scene chunk;
- car, richer effects, and high-quality assets according to the selected quality tier;
- audio nodes only after START THE DRIVE.
If reduced motion, saved pause, or static mode is known before step 4, the Three.js chunk and live scene assets are never requested. Project video uses preload="none". Automatic source attachment/loading begins only within 300 CSS pixels of the viewport when full motion is permitted and data saver is off. In reduced-motion, static, saved-pause, or data-saver mode, video sources remain detached until the visitor explicitly presses Play; that request is allowed and does not enable ambient scene motion. Video pauses, detaches its source, and releases active decoding when fully offscreen, retaining its poster and current-time intent for a later explicit resume.
Quality tiers:
- High: full effects within the performance budget.
- Medium: reduced particles, terrain detail, and post-processing.
- Low: simplified geometry, no costly bloom/atmospheric passes, capped pixel ratio.
- Static: composed poster, semantic HUD, and all content/navigation.
User-selected quality is a maximum tier, not a guarantee. Initial maximum tier is Static when reduced motion or saved pause/static preference applies; otherwise Low below 768 CSS pixels or with a primary coarse pointer, Medium from 768–1279 CSS pixels, and High at 1280 CSS pixels or wider with a primary fine pointer. A saved quality choice caps that maximum.
Adaptive sampling uses continuous epochs in which page lifecycle is active, document is visible, and scene state is running. Every exit from that conjunction—including manual pause, loading/static/lost, hide/freeze, or teardown—discards the RAF baseline and incomplete window; every re-entry establishes a new baseline and waits two visible running seconds before sampling. Eligible intervals have both endpoints inside the same epoch. An interval >250 ms wholly inside one epoch is catastrophic: High/Medium downgrades one tier immediately, Low enters Static immediately, and the normal downgrade reset/cooldown begins. No pause/hidden/non-running gap can become a sample. Other samples enter a non-overlapping window that closes only after both five visible running seconds and 120 eligible samples. Sort the window ascending and use nearest-rank p95 at index ceil(0.95 × n) - 1. At closure, High downgrades one tier when p95 >20 ms and Medium downgrades one tier when p95 >25 ms. Low increments a consecutive-bad-window counter when p95 >40 ms and resets it to zero otherwise; two bad Low windows enter Static. After a downgrade, discard samples and ignore quality decisions for 30 visible running seconds, then begin a new warm-up/window. Resize/orientation and manual quality changes discard the current epoch/window and bad-window counter. Resize/orientation recomputes the maximum and may downgrade immediately but never automatically upgrades. A deliberate manual quality change may upgrade only within the current maximum. System reduced motion, manual pause, and WebGL failure take precedence.
Desktop device pixel ratio is capped at 2; mobile/tablet is capped at 1.5. The renderer pauses when the page is hidden. Context recovery follows the scene lifecycle above. Failure of the Three.js chunk, shader compilation, model/texture load, first frame, WebGL, poster/video media, hydration, or Web Audio must not hide content or contact links.
With JavaScript disabled or the hydration entry unavailable, the pre-rendered portfolio, project descriptions, infrastructure story, toolkit, native anchors, and contact links remain usable. Interactive controls that require JavaScript are absent or visibly inert without obscuring the static experience.
14. Performance targets
Pre-release lab gates
Performance release gates run on two pinned physical reference classes: a Google Pixel 6 with 8 GB RAM for Mobile Low and an Apple M1 MacBook Air with 8 GB RAM for Desktop High. A documented device with the same CPU/GPU and RAM is equivalent; faster substitute hardware is not. Both are fixed to 60 Hz (Pixel Smooth Display off; Mac display set to 60 Hz). Battery is above 50%, power saving is off, the device is cool at the start, no other foreground application runs, and browser/OS/display-mode versions are recorded. The median of the first 120 eligible warm-up RAF intervals must be within 1 ms of 16.667 ms or the run is invalid.
Mobile profile: Chromium, 390×844 CSS pixels, no CPU emulation, 1.6 Mbps downstream, 750 Kbps upstream, 150 ms round-trip latency.
Desktop profile: Chromium, 1440×900 CSS pixels, no CPU emulation, 10 Mbps downstream, 40 ms round-trip latency.
The versioned drive-trace.v1 harness performs five runs per profile. Each run starts a new temporary browser profile; unregisters service workers; clears Cache Storage, HTTP cache, cookies, local/session storage, and IndexedDB; has no saved portfolio preferences; sets prefers-reduced-motion: no-preference, Save-Data: off, page zoom 100%, and audio state idle; and navigates from about:blank. Failure to receive load within 10 seconds, an LCP entry within 10 seconds, or the pinned live tier's first successful frame within five seconds after load fails the run. After running, the page remains visible for two warm-up seconds; that completion is interaction-trace t=0.
drive-trace.v1 lasts exactly 20,000 ms and uses Chromium DevTools Protocol trusted input. For each button/link action at time t, the harness samples its visible bounding box at t-50 ms, requires one stable enabled target, sends mouseMoved to its center at t-20 ms, left mousePressed at t, and left mouseReleased with clickCount=1 at t+40 ms. Wheel input uses Input.dispatchMouseEvent type mouseWheel at the safe-area-adjusted visual-viewport center with deltaX=0, pixel-mode deltaY, and no modifier. Each burst is six deltas of exactly +100 or -100 CSS pixels at start + {0,40,80,120,160,200} ms; positive scrolls the document forward/down. No OS acceleration or line-mode conversion is applied.
The initial volume after activation is exactly 40% (min=0, max=1, step=.05). At 2350 ms, CDP sends Tab keyDown then keyUp at 2370 ms and requires the immediately following visible tabbable control to be the author-owned volume slider. At 2400 ms it sends ArrowLeft keyDown and at 2440 ms keyUp, producing exactly 35%; that ArrowLeft interaction is the measured volume action. All other “Activate” rows use the pointer sequence above. Actions are dispatched at their listed offsets without implicit waits. A navigation may still be settling when a later wheel action deliberately cancels it through the production navigation-epoch path.
| Offset | Exact action |
|---|---|
| 0–999 ms | Idle; no input |
| 1000 ms | Activate Start the Drive |
| 1500, 2800, 4100, 5400, 6700, 8000 ms | Six down bursts, in that order |
| 2400 ms | Set volume to exactly 35% through the visible volume control |
| 3700 ms | Activate Mute |
| 5000 ms | Activate Unmute |
| 6300 ms | Activate Pause motion |
| 7600 ms | Activate Resume motion; the requested pause is therefore 1300 ms |
| 8900 ms | Activate the native Toolkit navigation link |
| 9300, 10600 ms | Two up bursts, in that order |
| 11900, 13200 ms | Two final down bursts, in that order |
| 14500 ms | Activate the native Contact navigation link |
| 14501–20000 ms | No further input; navigation settles through production logic |
For the Toolkit cancellation assertion only, the authenticated test build exposes a deterministic navigation-settlement barrier. The harness arms it before the 8900 ms activation; it permits the production push/scroll/epoch code to run but holds the epoch's settle/focus completion pending. The trusted 9300 ms wheel burst must increment the production epoch, invalidate that exact pending job, and release the barrier. The hook cannot create, cancel, or mutate an epoch itself and is absent from production bundles. This tests cancellation rather than depending on an arbitrary smooth-scroll duration.
The eight measured action oracles are exact. “Double RAF” below means the second page RAF after the named synchronous state mutation; it must complete by the same deadline and prove a rendering opportunity, but it does not replace the separate asynchronous lifecycle assertions.
| Measured action | Required production state mutation | State and render deadline |
|---|---|---|
| Start the Drive | increment audioIntentGeneration once; set desiredAudioState='running'; expose the activating/audio control surface |
500 ms; actual running or explicit user-recoverable failure remains covered by the audio lifecycle gate |
| Volume ArrowLeft | set the visible slider value and production gain target to exactly 0.35 |
500 ms |
| Mute | set muted=true and production output gain target to zero |
500 ms |
| Unmute | set muted=false and restore the production gain target to 0.35 |
500 ms |
| Pause motion | set desiredMotionState='paused' and cancel the sole scheduled scene RAF; no scene callback may begin after one expected frame period |
500 ms |
| Resume motion | set desiredMotionState='running' and schedule exactly one current-generation scene RAF; the pinned live tier must not enter terminal Static |
500 ms |
| Toolkit navigation | create exactly one new navigation epoch, set its requested fragment to #toolkit, and perform exactly one matching history mutation; settlement/focus is deliberately outside this latency oracle, while the armed test barrier makes the 9300 ms wheel's cancellation of that exact pending epoch deterministic |
500 ms |
| Contact navigation | create exactly one new navigation epoch, set its requested fragment to #contact, and perform exactly one matching history mutation |
500 ms; separate trace-end assertions require final alignment and focus settlement |
The run fails if any scheduled action cannot find one enabled visible target, if the trace becomes hidden, or if a navigation/load/LCP timeout occurs. Named-tier budget runs pin the actual tier—High on Desktop and Low on Mobile—and disable adaptive tier decisions while leaving the production renderer, controller, assets, and instrumentation unchanged; any observed tier change invalidates the run. A separate production-controller test replays the same frame-time windows with adaptation active and asserts the §13 downgrade/cooldown behavior. No named-tier budget result is used as evidence for adaptation correctness.
Metrics use the following executable definitions. All comparisons use unrounded DOMHighResTimeStamp values; reports round to three decimals only after pass/fail. Nearest-rank p95 sorts ascending and selects index ceil(0.95 × n) - 1.
- LCP: the latest
largest-contentful-paintentry observed before the first trusted user input or the document becoming hidden; itsstartTimeis the result. Absence by the timeout fails the run. - CLS: ignore
layout-shiftentries withhadRecentInput=true; group the remainder into session windows that start with the first entry and close when the gap from the previous entry exceeds 1000 ms or the window exceeds 5000 ms from its first entry. CLS is the largest window sum over navigation through trace end. An entry that causes either limit begins the next window. - Lab total blocking time: for each long task
[taskStart,taskEnd), sum the duration ofintersection([taskStart+50 ms, taskEnd), [FCP,t=0)). Missing FCP fails the run. Every long task that intersects[t=0,t=20000)fails the separate post-running long-task gate, including a task that began beforet=0. - Scripted control event-to-next-paint: instrumentation records an action ID, target, trusted press/keyDown time, production-handler acknowledgement, the exact corresponding state mutation from the eight-row oracle above, and its double-RAF confirmation. Event Timing is feature-detected and observed with
{type:'event', buffered:true, durationThreshold:16}. For each of the eight measured actions, entries must match target and the[dispatch, dispatch+500 ms]window; group equal non-zerointeractionIdvalues and take maximum duration. AftertakeRecords()at 500 ms, absence of an Event Timing entry is conservatively recorded as a<16 msupper bound of 16 ms only when the API is supported, exactly one trusted dispatch was acknowledged, that row's exact required mutation was observed by its deadline, and its double-RAF completed. Unsupported observation, absent acknowledgement/state/rendering confirmation, or ambiguous groups fails the run. The p95 uses the eight results; the volume result is the single ArrowLeft interaction, not the setup Tab. Navigation alignment/focus and audio-context completion are explicitly evaluated by their separate lifecycle oracles, not inferred from this latency metric. - Scene CPU and continuity: use paired marks around the complete production update-plus-render callback. Partition
[t=0,t=20000)into maximal contiguous intervals where overlay is active/visible and scene state isrunning; paused/static/loading intervals produce no scene measure. For each interval[a,b)lasting at least one expected frame period, require at least one callback,firstCallbackStart-a ≤3×expectedFramePeriod, every adjacent callback-start gap≤3×expectedFramePeriod, andb-lastCallbackEnd ≤3×expectedFramePeriod. Sumfloor((b-a)/expectedFramePeriod)asexpectedSceneCallbacks; actual callbacks across the same intervals must be at least 90% of that total. Zero intervals/samples or any boundary/gap failure fails the run. - Lost-presentation share: an instrumentation-only page-level RAF sentinel, independent of the scene loop, records timestamps throughout
[t=0,t=20000).expectedFramePeriodis the verified warm-up median. For every interval whose endpoints lie inside the trace,opportunities=max(1, round(interval/expectedFramePeriod))andlost=opportunities-1. Share issum(lost)/sum(opportunities).sum(opportunities)must be at leastfloor(20000/expectedFramePeriod)-3; otherwise the run fails. This counts a 100 ms stall as multiple lost presentation opportunities. - Unexpected late shift: every
layout-shiftentry withhadRecentInput=falsewhosestartTimeis at or after the first successful scene frame and before trace end. The allowlist is empty; the required count is zero.
| Metric | Per-run requirement | Five-run aggregation |
|---|---|---|
| LCP | worst ≤3.0 s | median ≤2.5 s |
| CLS | ≤0.1 | every run passes |
| Total blocking time | worst ≤300 ms | median ≤200 ms |
Long tasks after running |
no task >50 ms | every run passes |
| Event-to-next-paint for the scripted controls | p95 ≤200 ms | every run passes |
| Scene CPU update/render callback | Desktop High p95 ≤12 ms; Mobile Low p95 ≤24 ms | every run passes |
| Scene callback continuity | ≥90% expected callbacks; no running-state gap >3 frame periods | every run passes |
| Lost-presentation share | Desktop High ≤5%; Mobile Low ≤10% | every run passes |
| Late media/font layout shifts | zero unexpected entries | every run passes |
The frame-cadence gate captures scheduler/presentation stalls that a CPU callback timer alone misses; the CPU gate remains separately attributable to the scene code.
Every media component provides intrinsic width/height or aspect-ratio. Icon and diagram geometry is reserved. Self-hosted fonts use a deliberate font-display strategy and fallback-metric overrides.
Transfer and runtime budgets
All transfer figures are Brotli-compressed unless the format is already compressed:
- initial HTML plus critical CSS: ≤100 KB;
- initial Vue/application JavaScript excluding Three.js: ≤120 KB;
- hero/static poster: ≤220 KB;
- all initially required fonts: ≤120 KB;
- deferred Three.js, car, and first live-scene payload: ≤650 KB total;
- each project video: ≤2.5 MB, ≤10 seconds, maximum 1280×720 delivery rendition;
- no project video bytes before the 300 CSS-pixel activation threshold;
- each responsive project still rendition: ≤400 KB; each chart rendition: ≤100 KB;
- all deferred project stills/charts/diagrams/icons across the site: ≤2.5 MB total;
- high-tier scene extras beyond the first live-scene payload: ≤750 KB;
- aggregate non-video deferred transfer after the initial application: ≤3.5 MB;
- at most two image/scene asset requests and one video request execute concurrently;
- mobile/tablet texture dimension: ≤2048 pixels per side;
- Low-tier live GPU asset estimate: ≤96 MB; High-tier estimate: ≤192 MB.
Every shipped artifact belongs to exactly one versioned budget-manifest bucket; CI rejects unclassified or double-counted files. GPU estimates use decoded sizes: textures are width × height × bytes-per-pixel × layers/faces × 4/3 when mipmapped; geometry is the byte length of vertex, index, and instance buffers; render targets are width × height × bytes-per-pixel × attachments × sample count; and the total adds framebuffer/depth buffers, post-processing ping-pong targets, plus a fixed 32 MB runtime allowance. Test builds maintain an allocation ledger at resource creation/disposal and assert its formula-derived total at Start, Infrastructure sign, Selected Builds with active media poster, and Destination at maximum tier DPR. The ledger, not a non-standard browser memory API, is the auditable gate; optional platform memory observations are advisory.
CI fails when bundle, asset, concurrency, or GPU-accounting budgets are exceeded. Scroll and resize handlers perform no synchronous layout loop and batch reads before writes.
Post-launch field goals
The non-gating field goals remain p75 LCP ≤2.5 seconds, INP ≤200 ms, and CLS ≤0.1 over the standard 28-day window. The initial release does not add RUM or analytics to measure them. They are evaluated through privacy-respecting external tools such as Search Console when sufficient data becomes available. Any future first-party RUM design requires a separate privacy review, explicit field allowlist, retention policy, processor review, and approval before code is added.
15. SEO and discoverability
Ranking first or second for a name cannot be guaranteed, but the implementation must remove technical barriers and establish a consistent identity signal.
- The first HTML response contains the complete readable portfolio rather than an empty client-side shell.
- The exact H1 is Luca Pîslaru. The hybrid role is an immediately adjacent visible subtitle. The page title is Luca Pîslaru — System Administrator & Full-Stack Developer.
- A concise meta description explains the same identity naturally.
- The document has the correct language declaration, canonical URL, crawlable native links,
robots.txt, and an XML sitemap. - Production uses a single preferred host and protocol with permanent redirects from alternatives.
- JSON-LD uses one
ProfilePagewith a nestedPerson, canonical name, role description, site URL, and only the configured, verifiedsameAslinks. - Project links use descriptive anchor text.
- Private projects are described without identifying names or private URLs.
- Production Open Graph/social metadata uses the canonical title, concise description, absolute URL, and one licensed/approved preview asset from the asset register.
- After deployment, the production site is registered with Google Search Console and submitted through its sitemap.
- Luca's public profiles should link back to the canonical portfolio where those platforms permit it.
- Copy naturally includes the public name and relevant professional terms; it does not repeat keywords mechanically.
The canonical production domain and contact email are required before deployment. Each social profile is optional and appears only when configured and verified.
Non-production builds never emit production canonical/sitemap submission behavior. Every externally reachable preview/staging deployment requires provider/edge authentication; deployment fails if authentication cannot be enabled. Preview responses use the same CSP, anti-framing, referrer, MIME, and permissions controls as production, plus Cache-Control: private, no-store and X-Robots-Tag: noindex, nofollow, noarchive. HSTS is applied only on hosts already covered by an approved HTTPS policy. Preview omits production sitemap publication and Search Console registration. robots.txt is defense in depth, never access control.
SEO verification contract
The production response is fetched with JavaScript disabled and must contain exactly one H1, the correct lang, an absolute canonical URL returning 200, canonical name in title/H1/JSON-LD, one valid ProfilePage containing Person, only verified sameAs entries, sitemap URLs on the preferred host, and a robots policy that allows the canonical page. Every alternate protocol/host reaches the canonical URL through one permanent redirect. Search Console submission is recorded as a post-deployment action rather than a build gate.
16. Security, hosting, and supply-chain contract
Browser security baseline
Production responses—not only HTML meta tags—provide:
- a restrictive Content Security Policy with
default-src 'self',script-src 'self'plus the build-generated hash for the JSON-LD block,style-src 'self',img-src 'self',media-src 'self',font-src 'self',connect-src 'none',object-src 'none',base-uri 'none',frame-ancestors 'none',form-action 'none', andupgrade-insecure-requests; Strict-Transport-Security: max-age=31536000;includeSubDomainsis added only after every subdomain is verified HTTPS-ready;X-Content-Type-Options: nosniff;Referrer-Policy: no-referrer;- least-privilege
Permissions-Policydisabling camera, microphone, geolocation, payment, USB, accelerometer, gyroscope, and magnetometer; X-Frame-Options: DENYas a compatibility companion to CSP anti-framing.
The deployed response is tested for these headers. No executable asset, font, icon, image, shader, or media file is hotlinked from a CDN or third-party host.
Provider-neutral hosting contract
The selected static host must support HTTPS, one-hop permanent preferred-host redirects, Brotli/Gzip, immutable long-lived caching for hashed assets, revalidation for HTML, correct MIME types, byte-range requests for video, header configuration, atomic deployment or equivalent rollback, and authenticated/noindex preview controls. Release evidence records a successful production smoke test and the previous deploy identifier or rollback method.
Production browser source maps are disabled and absent from public output. If hidden maps are ever required for private error analysis, they are uploaded to an access-controlled service and removed from the published artifact; the build verifies that neither .map files nor sourceMappingURL references are reachable.
Supply chain
- The repository commits an exact package lockfile and uses reproducible clean installs in CI.
- CI actions are pinned to immutable commit SHAs.
- Runtime and development dependencies receive vulnerability and license scanning; known Critical/High vulnerabilities fail release, while Medium findings require documented triage before release.
- The complete tooling image and native media/OCR/barcode/transcoding/sanitization executables receive vulnerability scanning and signature/provenance verification; an unsigned/unverifiable image or known Critical/High finding fails preparation and release.
- Secret scanning covers tracked source, history, generated artifacts, and CI configuration.
- A CycloneDX or SPDX SBOM is generated for each production build.
- Unreviewed dependency lifecycle scripts are prohibited; any necessary install script is explicitly documented and approved.
- Asset and dependency provenance, version/hash, owner, license, and reviewer are recorded.
- The build checks license obligations and produces the distribution notices file.
Least-privilege release stages
Release stages are separated and artifact-digest-bound:
-
Dependency review inspects the lockfile before installation.
-
Tooling image pins Node, package manager, OCR/barcode scanner, transcoder, sanitizer, and build-image versions/digests.
-
Private preparation is networkless, credentialless, non-root,
no-new-privileges, capability-dropped, seccomp-confined, memory/CPU/time limited, and uses a read-only root filesystem with narrowly scoped read-only input and write-only ephemeral output mounts. Risky image/video/PDF/SVG decoders run in a separate disposable sandbox that receives one source at a time and cannot read the ledger; a second minimal projection process may read approved decoder outputs plus the ledger but cannot invoke decoders. The stage emits only allowlistedPortfolioContent, manifest, andPreparedAssetSet, then destroys both workspaces after hashing output. -
Approval projection attester is a separate minimal workload with an approval-authority non-exportable key, no raw-media decoder, and no publication/deployment credential. It independently reads current signed approval envelopes, protected live-ledger head/revision, all four closed production inputs, and the prepared asset hash index; recomputes/validates every canonical envelope, proof, record/asset root, input digest, and
productionInputRoot; and signs canonicalApprovalProjectionAttestationbytes. The attestation binds its schema, key ID/issuer epoch/scope,approvedRecordRoot,approvedAssetRoot,approvalProofSetDigest, all four labeled input digests,productionInputRoot, live-ledger head/revision, policy version, issue time, and earliest approval expiry. Its Ed25519 envelope uses the same canonical payload/signature rules as approval envelopes under its ownportfolio-approval-projection-attestation/v1schema. It is write-once control-plane evidence, never a fifth production/build input and never browser-visible. -
Install/build runs network-restricted with dependency lifecycle scripts disabled by default and with the four closed production inputs only. A necessary script is allowed only for an exact approved package/version/hash inside a credentialless sandbox.
-
Raw privacy workers and trusted reconciliation coordinator run in separate pinned networkless jobs. No object may receive a public-pass decision from one raw worker verdict. Each enumerated object/member is sent read-only to two independently built workers with different parser/scanner toolchains; complex containers and media use heterogeneous decoders, while plain files use independent byte/metadata scanners. Each worker binds its result to input digest, check type, normalized extracted-output/member digests, tool/image identity, and fail-closed typed verdict. A minimal trusted matcher, which cannot decode raw inputs, compares the two normalized result sets and applies the denylist/check rules to their agreed normalized evidence; any disagreement, unsupported surface, missing evidence, or single-worker result fails. Disposable workers and the matcher have no candidate-authoring, signing, publication, deployment, or overall-release authority and write only immutable per-digest reports.
A separate minimal coordinator independently enumerates the expected raw and prepared/built closure, requires the two worker reports plus matcher result for every applicable digest/check, rejects any missing/extra/duplicate report, reconciles every gate and tool/policy identity, and alone constructs canonical scan-evidence summary and candidate-release-manifest bytes. A parser/scanner cannot select the closure or declare aggregate success, and a schema-valid false pass from either authenticated worker is insufficient to authorize its object.
Candidate/evidence objects live in content-addressed write-once storage.
scanEvidenceDigest = J('portfolio-scan-evidence/v1', canonicalEvidenceSummary)andcandidateManifestDigest = J('portfolio-candidate-release-manifest/v1', canonicalCandidateManifest); retrieval must reproduce those exact canonical bytes. The candidate references theApprovalProjectionAttestationdigest and binds every artifact/pre-compressed hash; exact public ref map; source commit/tree and complete reachable object closure; LFS OIDs; release-archive hashes; all four labeled production input digests plusproductionInputRoot; deterministic input-to-output build-provenance record; exact live-ledger head/revision; both approval roots andapprovalProofSetDigest; scanner/policy/tooling versions; the full expiry tuple and requested manifest expiry bounded by its minimum; and protectedcurrentManifestDigest. On successful reconciliation, the CI control plane—not worker or coordinator code—issues a scoped non-exportableportfolio-privacy-workload-attestation/v1signature binding both object digests, measured worker/coordinator images, enumerator, policy, issue/expiry, and job identity. None can invoke a general signing interface. -
Release attestation signer is a separate minimal, network-restricted workload with a non-exportable release key and no ability to read/parse raw repository objects, assets, media, denylist, or private ledger. Through a constrained read-only content-addressed interface it retrieves the canonical candidate/evidence bytes by digest, recomputes both digests, and accepts the valid
ApprovalProjectionAttestation, privacy workload attestation, and independently supplied policy/tool-image attestations. It verifies every typed candidate/evidence field and coverage count; all signature scopes/key IDs/issuer epochs; exact prepared/build output and four-input provenance; proof/content/asset roots; scanner evidence completeness; tool/policy allowlists; the complete expiry tuple against trusted current time; and exact equality with protected live-ledger head/revision andcurrentManifestDigest. It then signs the exact canonical candidate bytes as the release manifest. Scanner, preparation, reconciliation, and publisher identities cannot call this signer. -
Fenced atomic public-visibility transaction receives only the scanned closure, signed release manifest, and narrowly scoped transaction credential. Protected state holds
currentManifestDigest, live-ledger head/revision, active transaction, and a monotonic fencing counter. After exact ledger/manifest/time checks, the coordinator durably allocates transaction ID/fencen+1; stages immutable Git objects/refs in a non-advertised namespace and deployment files in a non-public slot; records each phase before acting; and obtains immutable readiness receipts for both. Neither target is publicly reachable merely because it is staged or ready. Public Git advertisement and deployment serving both resolve through the same protected committed-release pointer.The sole visibility operation is one linearizable compare-and-swap over expected
currentManifestDigest, exact live-ledger head/revision, transaction ID/fence, both readiness-receipt digests, and the complete unexpired approval/attestation/manifest expiry tuple. Success atomically advances the committed-release pointer so both exact ready targets become visible together; failure leaves both hidden and the prior release visible. All target and resolver APIs enforce the current fence and expected prior pointer, so a resumed stale writer cannot mutate visibility. Process death or lease expiry blocks new publication until durable recovery obtains a newer fence: before expiry it may retry the same final CAS, while at/after any bound expiry it may only abort, retain/restore the prior committed pointer, and garbage-collect hidden staging. A crash before CAS exposes nothing new; a crash after successful CAS observes an already-complete committed state. Branch protection and the public resolver reject direct public pushes or ungated ref advertisement.
No stage after trusted reconciliation may alter files or ref/object closure; compression artifacts included in deployment are produced before scanning. Transaction admission, each readiness operation, the final CAS, and every recovery iteration recheck exact live-ledger equality and trusted time against every bound expiry. A ledger append or expiry fences and aborts the transaction; it can never complete publication. A controlled rollback creates and signs a new manifest against the protected current head and current approval state while binding the selected older artifact/closure; an old manifest is never replayed. Publication receipts record transaction/fence, signed manifest digest, both readiness receipts, committed pointer, resulting refs/deploy ID, and predecessor.
Every trust root has a distinct protected key ID, issuer epoch, narrow scope, rotation policy, and revocation list: approval decision, approval projection, privacy workload, policy attestation, tool-image provenance, release signing, and publisher/fencing credentials are never interchangeable. Compromise freezes publication and revokes the affected epoch. Approval-key compromise additionally audits from the last trusted ledger checkpoint, supersedes every decision that cannot be proven pre-compromise, and requires fresh approvals and roots. Projection compromise requires fresh independent projection; privacy-workload compromise requires a clean re-scan/reconciliation; policy-attestation or tool-image-provenance compromise invalidates every dependent candidate/workload/release artifact, requires freshly attested policy/image digests, and then requires a clean scan/reconciliation; release-key compromise invalidates unaccepted manifests and requires clean re-attestation/re-signing; publisher compromise increments the fence, rotates the credential, verifies the committed pointer/targets, and reconciles hidden staging. No release resumes until the corresponding fresh evidence and protected trust policy are committed.
17. Reference interpretation and licensing
The Nightdrive reference in The Gallery informs the moving-road concept, scroll-reactive speed, horizon composition, and environmental mood. The implementation is a fresh reinterpretation with an original car, section-sign system, destination sequence, content architecture, artwork, shaders, and audio.
The inspected reference is MIT-licensed. If any source code is copied or substantially adapted rather than independently implemented, its copyright and MIT license must be preserved in the repository and distribution notices. Reference audio, branding, text, and visual assets are not reused.
18. Testing strategy
Controller and state-machine tests
Unit tests use literal inputs and expected outputs rather than topic-only assertions. They cover:
- scroll
dt=0, negative/invaliddt, a multi-second hidden-page gap, maximum upward/downward deltas, zero scroll range, resize during smoothing, and NaN/Infinity rejection; - first/last-section boundaries, identical heading offsets, tall/short/overlapping sections, exact 35%-line pixels, two-pixel document-end behavior, both scroll directions, late layout growth, and orientation change;
- explicit navigation to different and already-current canonical fragments, exactly-zero versus exactly-one history mutation, navigation-epoch cancellation, native
scrollend, three-stable-frame fallback, 1500 ms final alignment, passive 150 ms replacement, direct fragments, popstate, user-scroll interruption, rapid back/forward, bfcache restoration, history-loop suppression, and the rule that only a still-current explicit in-page navigation moves focus; - HUD, navigation, environment, route state, and semantic active-section IDs agreeing no later than the next animation frame; sign target/phase separately matching forward-only eligibility, direct-entry into a skipped phase, pass completion, reverse clearing, >0.75vh/multi-boundary/Home/End/explicit/history suppression, and the no-latch result for a jump directly past completion;
- exact initial-tier mapping, running-epoch entry/exit baseline resets, manual-pause/resume gaps never becoming samples, lifecycle-proven hidden/non-running gap exclusion, catastrophic within-epoch >250 ms handling at every tier, non-overlapping five-second/120-sample closure, nearest-rank p95, one sample below/above each threshold, Low bad-window reset, 30-visible-running-second cooldown, window resets, no auto-upgrade, user maximum tier, and static precedence;
- every row of the motion/resource transition table, including runtime
matchMediachanges, in-flight import abortion, partial/full disposal or retention, video source attachment/detachment, explicit re-enable, and audio independence; - every scene lifecycle edge, including
loading → lostand conditional retained-contextpaused → lost; every scene-state × persisted-pagehide overlay row; F5 hidden versus frozen applicability; prohibition on frozen attachment; stale generation/abort behavior; exactly one canvas/animation loop; exactly-once partial/full disposal; non-persisted pagehide/unmount; context loss during loading/running/hidden states; hidden restoration pending; visible watchdog and first-subsequent-lifecycle-task enforcement of the monotonic cutoff; attach-time cutoff recheck; and permanent static mode after a later loss; - audio zero contexts before activation, one live context/graph after five rapid activations, every actual-state/table edge, quick hide/show while initialization remains
starting, interruption duringstarting, no-op visibility with user-required intent, actual-versus-desired reconciliation,starting → suspended/closed, mute/volume during startup, rejected start/resume/suspend, synchronous silence after suspend failure, browser interruption normalization, persisted/non-persisted page lifecycle, stale-operation cleanup, and exactly-once teardown; - strict deployment
siteConfig, private-ledger-to-public-root projection, publicPortfolioContent, link, safe-JSON-LD, public asset-manifest, and private-record validation.
Vue and SSR tests
- Server rendering produces the exact H1, adjacent role subtitle, all ordered headings, project records, infrastructure text, toolkit labels, and contact link.
- Hydration produces no unexpected mismatch and does not duplicate markup.
- Semantic landmarks, navigation state, controls, toolkit groups, chart descriptions, media controls, and accessible icon handling are correct.
- Private records never render repository/product links.
- Missing optional social profiles are absent from visible markup and
sameAswhile required email remains available. - Malicious configuration values using invalid schemes, credentials, control characters, protocol-relative URLs, or script-closing content fail the build safely.
- Explicit section navigation focuses the target heading; scroll/observer/history events do not move focus.
Raw-response and no-JavaScript tests
A raw built-HTML test and a browser run with scripting disabled assert the canonical H1, all eight journey section headings, experience/project descriptions, infrastructure evidence, toolkit labels, native section anchors, visible email, and primary mailto: link. A separate blocked/failed hydration-entry test proves the same content and native navigation remain usable.
Browser fault injection
Explicit test-only hooks inject each failure; production cannot activate them. The oracle is:
| ID | Trigger | Deadline | Required terminal state and presentation | Retry and cleanup |
|---|---|---|---|---|
| F1 | Three.js chunk, shader, car, or texture failure | 5 s from live-scene request | Scene static; poster visible; canvas/RAF count 0; motion control reads Visuals unavailable |
No automatic retry; refresh is the only retry; abort/dispose once |
| F2 | No first successful scene frame | 5 s from live-scene request | Same static/poster/control result | No automatic retry; dispose partial generation once |
| F3 | Exception after a successful frame | next animation frame | Scene static; poster replaces canvas; content remains stable |
No automatic retry; cancel loop and dispose once |
| F4 | First WebGL context loss while visible | immediate lost; evaluate by lostAt+5000 ms |
Restoration follows §11; success may attach only after current-generation and cutoff recheck; watchdog cutoff or rebuild failure becomes static | One rebuild only; dispose invalid/late generation before attach |
| F5 | First WebGL context loss while hidden/frozen | immediate lost when delivered; logical cutoff remains lostAt+5000 ms |
No rebuild while hidden; on the first subsequent lifecycle task, restore only if visible and still before cutoff, otherwise become static on that task | One rebuild maximum; no promise of a hidden-page wall-clock task; dispose invalid/late generation before attach |
| F6 | Any later WebGL context loss | next animation frame | Static/poster; canvas/RAF count 0 | No retry this session; dispose once |
| F7 | Poster failure | next render task | CSS gradient/static color fallback; no broken-image icon; accessible scene description remains | No automatic retry; one recorded media error |
| F8 | Project video failure | 3 s after request rejection/timeout | Poster remains, Play becomes Video unavailable, adjacent text description remains | No automatic retry; source detached/decoder stopped |
| F9 | Hydration entry failure | script failure/timeout observed by test harness | Server HTML/native anchors/mailto: remain; enhanced controls are absent |
No client retry; zero uncaught errors from page code |
| F10 | Web Audio initial start failure | rejected operation | Audio failed; control reads Audio unavailable |
No automatic retry; partial nodes disconnected/closed |
| F11 | Web Audio resume/interruption failure with intact silent graph | rejected operation | Audio remains suspended; visible Resume sound |
User-triggered serialized resume only; one graph maximum |
| F12 | Web Audio graph-invalidating/node-recreation failure | rejected operation or invalid-graph signal | Audio terminal failed; visible Audio unavailable |
No retry this session; partial/new nodes disconnected, old invalid graph torn down once |
| F13 | Hide/pagehide-triggered Web Audio suspend() failure |
rejected operation | Master gain becomes zero/output disconnects synchronously; actual state then failed; Audio unavailable when visible |
Close the one graph exactly once; no automatic retry; zero audible output after trigger task |
Every oracle also asserts H1 and all semantic sections remain present, private records omit links, focus/history remain usable, no duplicate context/canvas/loop/graph exists, cleanup counts match the lifecycle, and no unhandled rejection or uncaught error escapes the owning boundary.
Fault source-state applicability is normative; the browser matrix never requests an impossible Cartesian product:
| Fault | Legal source state/lifecycle variant |
|---|---|
| F1–F2 | scene loading only; F1 is repeated for chunk, shader, car, and texture subcases |
| F3 | scene running after at least one successful frame |
| F4 | first visible context loss from scene loading and separately running |
| F5 | visibility-hidden but non-frozen loss from loading and separately running; plus persisted-frozen loss only from paused with a complete retained generation formerly running. Formerly loading frozen state is excluded because its partial context was aborted/disposed. Test before-cutoff pageshow, after-cutoff pageshow, and late rebuild completion |
| F6 | scene running only after one successful F4/F5 restoration |
| F7 | initial poster request and poster fallback after F1 |
| F8 | project video requested from full-motion proximity loading and from reduced/static explicit Play |
| F9 | pre-hydration server-rendered state |
| F10 | audio actual starting during the first explicit activation only |
| F11 | audio actual suspended with intact graph, separately from visibility suspension and browser interruption |
| F12 | audio actual running and separately resumable suspended with an injected graph-invalid/node-recreation failure |
| F13 | audio actual starting and separately running when hide/persisted-pagehide requests suspend; never from already suspended |
Supported browser and viewport matrix
At release time, record and test the current and previous stable major releases of Chromium/Edge, Firefox, and desktop Safari, plus current iOS Safari and Android Chromium. A missing platform requires a documented blocking exception approved before release; “test environment unavailable” is not an automatic pass.
Automated visual/function coverage uses at least:
- 320×568 and 390×844 mobile portrait;
- 844×390 mobile landscape;
- 768×1024 tablet portrait and 1024×768 tablet landscape;
- 1280×720 compact desktop;
- 1440×900 standard desktop;
- 1920×1080 and 2560×1440 wide desktop.
The executable browser matrix is:
| Browser/OS release | Required viewports/states | Required fault rows and lifecycle variants |
|---|---|---|
| Current desktop Chromium | every automated viewport; default, audio-running, reduced-motion, manual-pause, Static, media-failure, missing-social, no-JS | F1–F13 at 1440×900 in every legal source/lifecycle variant from the applicability table |
| Current desktop Firefox | 390×844, 768×1024, 1440×900, 1920×1080; same named states | same F1–F13 applicable variants at 1440×900 |
| Current desktop Safari | 390×844, 768×1024, 1440×900, 1920×1080; same named states | same F1–F13 applicable variants at 1440×900 |
| Current desktop Edge | 390×844, 1440×900, 2560×1440; same named states | F1–F13 applicable variants at 1440×900 |
| Current iOS Safari on the named iPhone | portrait and landscape physical viewports; default, audio-running, reduced-motion, manual-pause, Static, media-failure, no-JS | F1–F13 applicable variants in portrait; F4–F6 and F10–F13 applicable variants in landscape; physical-drive.v1 |
| Current Android Chromium on Pixel 6 | portrait and landscape physical viewports; same named states | F1–F13 applicable variants in portrait; F4–F6 and F10–F13 applicable variants in landscape; physical-drive.v1 |
| Previous stable desktop Chromium, Edge, Firefox, and Safari majors | 390×844 and 1440×900; default, reduced-motion, Static, no-JS | F1, F4, F8, F9, F10, and F13 at 1440×900 |
Every matrix cell runs raw semantic/contact/private-link assertions and the geometric oracle in addition to its stated state/fault work. Each fault runs only in the applicability rows above; F10–F13 assert exact context/graph/output/control counts. Automated flash checks run on final media/scene captures for every current engine; previous majors receive the same shipped captures plus functional smoke. A skipped cell is a release blocker unless an explicit, time-limited exception names the exact cell, owner, reason, compensating evidence, and expiry.
A physical iPhone 13 with current iOS Safari and the Pixel 6 reference device with current Android Chromium run physical-drive.v1. Both use fixed 60 Hz (Pixel Smooth Display off), page zoom 100%, battery above 50%, power saving off, cool start, no other foreground app, and the Mobile network profile through the same hardware/router shaper. Exact device, OS, browser/driver build, viewport, refresh mode, battery, and thermal state are recorded. Website data/service workers/caches/preferences are cleared; the browser opens portrait at document top with chrome fully expanded, full motion, silent, and the production-selected maximum tier. After the first successful scene frame, p=0 starts this exact ten-minute script. When actions share an offset, table order is normative.
Physical mobile input uses exactly two W3C WebDriver input sources: pointer {type:'pointer', id:'driveTouch', parameters:{pointerType:'touch'}} and key {type:'key', id:'driveKeys'}. Mouse/pen fallback is forbidden. Read visualViewport and four fixed safe-area sentinels at cycle start. Define safeX=visualViewport.offsetLeft+safeLeft, safeY=visualViewport.offsetTop+safeTop, w=visualViewport.width-safeLeft-safeRight, and h=visualViewport.height-safeTop-safeBottom; any non-positive w/h fails. All coordinates use roundHalfUp(z)=floor(z+0.5) after adding the safe origin and every pointer move has origin:'viewport'.
A document-forward cycle is the literal driveTouch sequence: pointerMove(duration:0,x:roundHalfUp(safeX+0.5w),y:roundHalfUp(safeY+0.80h)); pointerDown(button:0); then for each i=1..15, pointerMove(duration:40,x:roundHalfUp(safeX+0.5w),y:roundHalfUp(safeY+h*(0.80-0.70*i/15))); pointerUp(button:0); pause(duration:400). Thus move endpoints occur at +40,+80,…,+600 ms, pointer-up is the next zero-duration tick, and the source is idle through +1000 ms. A document-reverse cycle uses the identical sequence with y=roundHalfUp(safeY+h*(0.20+0.70*i/15)), starting at 0.20h and ending at 0.90h.
Immediately before choosing each cycle direction, require document.scrollingElement, sample maxScrollY = max(0, scrollingElement.scrollHeight - scrollingElement.clientHeight) as an unrounded CSS-pixel double, and sample scrollY = clamp(scrollingElement.scrollTop, 0, maxScrollY). Direction begins forward and switches only when forward with scrollY ≥ maxScrollY-2, or reverse with scrollY ≤2. Cycle start offsets are every integer second in each half-open scrolling range below. Dynamic browser-chrome changes trigger the visual-viewport/safe-inset reread; orientation additionally recomputes maxScrollY and resets the next cycle to the new geometry without changing document direction.
Every table action named activate, navigate, pause, or resume uses driveTouch: sample the single visible enabled target box at p=t-100 ms and p=t-80 ms (each edge differs by <1 CSS px), compute its viewport-clipped center with roundHalfUp, then perform pointerMove(origin:'viewport',duration:0,center) at t-60 ms, pause(duration:60), pointerDown(button:0) at t, pause(duration:60), and pointerUp(button:0) at t+60 ms; require the row's stated state by t+500 ms. No mouse fallback, script .click(), or script .focus() is allowed. The 16 s volume operation uses driveKeys with WebDriver key values Tab \uE004 and ArrowLeft \uE012: Tab keyDown at 15.900 s, keyUp at 15.920 s, require the visible author-owned volume slider to own focus, then ArrowLeft keyDown at 16.000 s and keyUp at 16.040 s; assert exactly 35% by 16.500 s. All unspecified source ticks contain an explicit pause of the required duration so the two-source action matrix stays synchronized. OS background/foreground and rotation use the recorded platform automation driver; context/audio fault-hook invocations use the authenticated harness channel and are not DOM control actions.
| Physical offset | Action and assertion |
|---|---|
| 0–15 s | Idle portrait; assert one canvas/loop and the geometric oracle |
| 15 s | Activate Start the Drive through W3C pointer actions; at 16 s focus the volume slider and send one ArrowLeft from the 40% default to 35% |
| 30–120 s | Run cycles at 30,31,…,119 s using the exact direction rule above; this cadence exercises dynamic browser chrome |
| 120 s | Rotate landscape; wait exactly 5 s and assert safe-area geometry, one canvas/loop, and no tier above the recomputed maximum |
| 125–180 s | After the 125 s assertions, run cycles at 125,126,…,179 s |
| 180 s | Background through OS automation for 30 s; perform no page input |
| 210 s | Foreground; within 5 s assert one retained/rebuilt generation as allowed by lifecycle, one graph, and usable controls |
| 225 s | Invoke the deterministic test-only audio-interruption hook with an intact graph; at 227 s assert suspended and Resume sound, then activate Resume sound at 230 s |
| 250 s | Invoke first context loss; invoke restoration at 252 s while visible; by 257 s require exactly one current running generation or the specified terminal static fallback, never two |
| 270 s | Rotate portrait; wait exactly 5 s and re-run safe-area/geometric assertions |
| 275–510 s | After the 275 s assertions, run cycles at 275,276,…,509 s except 389 and 390 s. Arm the authenticated settlement barrier before activating Infrastructure navigation at 390 s; the 391 s cycle must cancel that exact pending job through the production epoch path and release the barrier |
| 510 s | Background for 30 s, then foreground at 540 s and assert lifecycle counts within 5 s |
| 550 s | If the scene is live, activate Pause motion and assert zero scene RAF within one frame plus the retained last canvas frame. If it is terminal static, send no pointer action and instead assert the poster, zero RAF, and disabled/unavailable motion state. Both branches retain audio independence |
| 565 s | In the live branch, activate Resume motion and assert one canvas/loop within 5 s. In the terminal static branch, send no pointer action and reassert the unchanged poster, zero RAF, unavailable motion state, usable non-motion controls, and audio independence |
| 575 s | Navigate to Contact |
| 580–600 s | No input; assert Contact settles, remains usable, and final geometry passes |
The physical harness logs state transitions, generation/context/loop/graph counts, quality tier, and geometry without collecting hardware identity or exporting telemetry. Deterministic interruption/context hooks are compiled only into the authenticated test build; a real OS notification/audio-focus interruption is an additional advisory observation because native interruption delivery cannot be made identical across both platforms. Pass means no crash; no unhandled exception/rejection; no duplicate context, canvas, loop, or graph; no geometric failure; and no loss of touch/keyboard controls. Automatic quality transitions must be monotonic non-increasing, contain no automatic upgrade, observe the 30-visible-second cooldown, and make at most one step per eligible decision window; this is the literal meaning of “no uncontrolled quality oscillation.” General low-memory behavior remains advisory because consumer-device memory pressure cannot be injected reproducibly enough to be a hard gate.
Accessibility verification
Release requires zero unresolved failures of every applicable WCAG 2.2 Level A and AA success criterion. Automated tools support but never replace the recorded manual criterion checklist; all automated violations, regardless of impact label, are resolved or documented as false positives with evidence.
Automated and manual states include default, audio-running, static, reduced-motion, media-failure, and missing-social. Keyboard-only traversal reaches Contact in logical document order; focus is visible and never obscured by fixed HUD/controls. Test 320 CSS-pixel viewport reflow separately from desktop 400% zoom configured to an effective 320 CSS-pixel content width. WCAG text-spacing overrides and forced-colors mode preserve content and controls.
Named manual pairs include NVDA with Firefox on Windows and VoiceOver with Safari on macOS/iOS. Versions, state, and results are recorded for these literal tasks and oracles:
- On load, announce document title, skip link, one H1, adjacent role, navigation, and one concise scene description; canvas/signs never appear as separate accessible objects.
- Activating skip/navigation links announces the correct target heading and places focus there; manual scrolling/history restoration leaves focus and reading cursor unchanged.
- Start the Drive is a button with its supporting description; activation exposes correctly named mute/volume controls and the resulting audio state without repeated live announcements.
- Toolkit tiles announce each technology once, not both icon and label.
- Chart groups expose caption, axes/variables, trends, conclusion, and data table when required without relying on color/image inspection.
- Video exposes name, play/pause state, description/caption, unavailable fallback, and no unexpected autoplay under reduced motion.
- Contact exposes visible email, primary
mailto:purpose, and correctly named optional profile links.
Motion/video controls, reduced-motion behavior, touch target size, contrast, non-color cues, and three-flash analysis pass in every named state.
Geometric layout oracle
For every automated viewport, let root=document.documentElement; require root.scrollWidth ≤ root.clientWidth + 1 CSS px. Four inert fixed test sentinels sized from env(safe-area-inset-left), -right, -top, and -bottom provide safeLeft, safeRight, safeTop, and safeBottom from computed bounding boxes. In layout-viewport coordinates the allowed rectangle is [visualViewport.offsetLeft+safeLeft, visualViewport.offsetTop+safeTop, visualViewport.offsetLeft+visualViewport.width-safeRight, visualViewport.offsetTop+visualViewport.height-safeBottom]. Every non-decorative text/control/media bounding box remains within its horizontal interval with 1 px tolerance; the currently focused control and every fixed HUD/control surface also remain inside its vertical interval. Text is not clipped by overflow:hidden. The physical-input harness uses these exact four sentinel values and formulas.
Every enabled author-owned pointer target is at least 44×44 CSS pixels except an inline text link inside a sentence/paragraph. That sole exception must carry data-target-size-exception="inline-link"; CI fails any other exception value or an exception whose DOM role/context does not match. Native media controls are not exposed or used by the portfolio, so inaccessible user-agent shadow-DOM controls are outside the application target inventory rather than falsely annotated. The same rule is used in the WCAG checklist. When focus is outside a fixed control surface, its bounding box has zero intersection area with fixed HUD/control boxes after the browser aligns it with at least 16 CSS pixels of scroll-margin. The complete focus indicator remains inside the allowed horizontal interval and visual-viewport vertical bounds. Bounding-box assertions are followed by visual regression review; decorative scene overflow is explicitly excluded.
Privacy, licensing, and supply-chain verification
- Every public asset has a complete clearance record and approved output hash.
- OCR/manual review and video-frame/container review use final encoded artifacts.
- Seeded privacy canaries fail the pipeline across every named leakage surface without printing the denylist.
- QR/barcode canaries fail and production scans report coordinates without decoded payload.
- Nested/encrypted/bomb/malformed/traversal/symlink/OOXML/LFS container canaries fail closed at the stated resource limits, and every successfully extracted member receives the complete applicable gate set.
- Every emitted content/manifest record has exactly one current signed approval; canonical-envelope and typed-root vectors are reproduced byte-for-byte in independent implementations and reject alternate signature encodings, duplicate JSON keys, non-NFC strings/paths, duplicate/missing/extra/ambiguous IDs, invalid issuer/role/signature/hash-chain/freshness/expiry/exact-record/output binding, and anti-rollback failures. Forged, unauthorized, expired, revoked, reordered, removed, replayed, claim-mutated, and output-substitution fixtures fail.
ApprovalProjectionAttestationsignature, canonicalapprovalProofSetDigest, exact four input digests,productionInputRoot, both approval roots, live-ledger head/revision, policy, and complete expiry tuple are independently verified. Prepared-asset index/path/byte substitutions, site-config changes under a reused build ID, fabricated roots, output swaps, stale live heads, later rejection/revocation appends, and wall-clock expiry without a ledger append fail at preparation, attestation, release signing, readiness, recovery, and final visibility CAS.- Before every public-mirror publication, the full commit/tree/blob/ref/LFS/archive and artifact privacy scans pass; the signed release manifest binds the exact closure/artifacts/policy/live-ledger head/revision/approval roots. Extra/substituted items, stale/replayed manifests, forked previous hashes, and two concurrent publications fail.
- Scanner-compromise tests prove raw parser workers cannot select closure, author candidates, declare aggregate success, access a signing identity/interface, or mutate write-once evidence; an authenticated worker returning a schema-valid false pass is rejected by the independent worker/matcher disagreement rule. Fixtures also cover omitted/reordered normalized members and matching digest with mismatched check type, normalized output, or worker image. The trusted coordinator rejects missing/extra/forged per-digest reports, and the release signer retrieves/recomputes canonical candidate/evidence bytes before semantic verification. Forced process death before/after every stage/readiness operation/final CAS, a ledger append between every check and mutation, expiry crossing without a ledger append, lease expiry, stale-writer resumption, partial target failure, and concurrent-start tests prove neither new target is reachable before one successful atomic visibility CAS and the prior committed release remains coherent after every failed CAS.
- Compromise drills cover approval, projection, privacy-workload, policy-attestation, tool-image-provenance, release-signing, and publisher/fencing issuer epochs independently. They verify freeze/revocation, checkpoint audit and reapproval where required, fresh policy/image attestation, projection or scan, dependent candidate/workload/manifest invalidation, credential rotation/fence advance, hidden-stage reconciliation, and refusal to resume with an old epoch.
- Public
PortfolioContent, manifest,PreparedAssetSet,siteConfig, SSR/client bundles, and compressed output contain no private ledger key/value, source path, approver/evidence metadata, private link, public source map, external asset URL, prohibited identifier, real/linkable/derived PII/health data, credential, or unapproved infrastructure detail. - Clean-install lockfile reproduction, dependency/license scan, secret scan, SBOM, pinned CI action, and distribution-notice checks pass.
19. Acceptance gates
Build-ready gate
The artifact is build-ready only when:
- all four closed production inputs validate, every prepared asset is exactly manifest-bound with no extra/missing file, and no placeholder or unapproved record exists;
- raw and no-JavaScript HTML contains the complete semantic portfolio;
- required privacy, factual, licensing, and asset approvals pass;
- bundle/media/runtime budgets and five-run lab performance gates pass;
- every supported automated viewport passes the geometric layout oracle and visual review;
- active section, HUD, navigation, environment, and route IDs synchronize within one animation frame, while any visible sign matches the independent §12 latch/phase oracle;
- reduced-motion users request no Three.js or automatic video payload;
- scene/audio lifecycle, fault-injection, keyboard, accessibility, browser, and physical-device gates pass;
- canonical H1 is Luca Pîslaru, the adjacent subtitle is the hybrid role, and the title contains both;
- no private link, CV download, AI-generated project image, fake metric, heatmap, portrait, analytics/tracking technology, or public source map exists;
- the three-person evidence-first audience check meets its comprehension and professionalism thresholds.
Production-deployed gate
The production deployment is complete only when:
- canonical HTTPS URL returns 200 and every alternate host/protocol permanently redirects in one hop;
- CSP, HSTS,
nosniff, Referrer Policy, Permissions Policy, and anti-framing headers match the contract; - HTML revalidation, immutable hashed-asset caching, compression, MIME types, and video byte ranges work;
- canonical, JSON-LD, Open Graph metadata, robots, and sitemap validate against the production host;
- the deployed page passes a JavaScript-disabled smoke test and the representative device/browser smoke tests;
- the privacy gate has run against the exact deployed artifact hash;
- rollback method/previous deploy identifier is recorded;
- Search Console ownership and sitemap submission are completed as post-deployment actions.
20. Implementation boundary
This specification is one coherent implementation project: one pre-rendered portfolio document, one persistent optional live scene, one journey controller, one optional audio system, one content/asset clearance pipeline, and one responsive semantic content experience. The production host may be selected during implementation planning, but its deployment must satisfy the provider-neutral contract and emit host-specific metadata/artifacts from validated configuration.
Implementation does not begin directly from this document. The next step, after independent re-review and user approval, is a detailed implementation plan that sequences content/register work, asset sanitization, pre-rendering, semantic UI, journey state, scene/audio lifecycles, responsive behavior, accessibility, testing, performance, security, and deployment verification.