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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and

### Changed

- Source Vault stems: the remastered stems are in. Each track's zip holds its WAV stems and MIDI files (10–12 stems per track, every one as WAV + MIDI), and the stem lists now match the real files. ALL STEMS hands over the 20 track zips one after another (a chapter zip would pass GitHub's 2 GB per-file cap). The per-stem WAV / MIDI chips are labels now, not mock-up buttons.
- Source Vault phone menu: one link is always lit with the gradient, like the site's menu. At the top of the page that's PROMPTS, the first section.
- Source Vault phone menu: it now opens exactly like the site's menu: full screen with the slat wipe, the SYS::OPEN chip, big outlined poster links with numbered captions (the section you're on fills with the gradient), and the split buttons at the bottom.
- Source Vault menu: the links now follow the page, top to bottom: Prompts, Harmonic Map, Tracks, Credits (desktop nav and the phone menu).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ The page is public code, so the private parts are locked:

**Changing the key, prompts or analysis:** edit `.env.vault` (`VAULT_KEY=…`) or the files in `vault-private/` (both git-ignored), run `npm run vault:encrypt`, and commit the two regenerated files.

**Updating the stems:** upload the zips to the `stems` release on the private repo using the names `npm run vault:encrypt` prints (one per track, plus one per chapter for ALL STEMS, since GitHub caps a release file at 2 GB). Sizes appear in the vault automatically.
**Updating the stems:** upload the zips to the `stems` release on the private repo using the names `npm run vault:encrypt` prints (one per track, holding `WAV/` and `MIDI/` folders; ALL STEMS downloads all 20, since even one chapter's zip would pass GitHub's 2 GB cap per release file). Sizes appear in the vault automatically.

**Strength:** the key protects the files like a password on a zip. Someone could copy `data.enc.json` and try guesses offline, so use a long, unusual key if the contents need to stay secret from determined people.

Expand Down
2 changes: 1 addition & 1 deletion netlify/vault-proof.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"proof":"61cfcf5de89c4968f2bdca4a0e000bd8351212e3322afc707bb937fe6b8096ff","assets":["01_origin_stems.zip","02_left_behind_stems.zip","03_graft_stems.zip","04_impacted_stems.zip","05_empty_city_stems.zip","06_the_feed_stems.zip","07_gospel_out_stems.zip","08_endless_glow_stems.zip","09_awake_stems.zip","10_reclaimed_stems.zip","11_the_wreckage_stems.zip","12_read_stems.zip","13_come_home_stems.zip","14_changed_the_lock_stems.zip","15_down_the_front_stems.zip","16_whole_stems.zip","17_enough_stems.zip","18_open_sky_stems.zip","19_all_of_me_stems.zip","20_better_days_stems.zip","ARCHIVE_404_stems_01_origin.zip","ARCHIVE_404_stems_02_the_feed.zip","ARCHIVE_404_stems_03_the_wreckage.zip","ARCHIVE_404_stems_04_whole.zip"]}
{"proof":"24349a10f58e80c01132252af809683267c13a57d1c286716c5717b2165d282c","assets":["01_origin_stems.zip","02_left_behind_stems.zip","03_graft_stems.zip","04_impacted_stems.zip","05_empty_city_stems.zip","06_the_feed_stems.zip","07_gospel_out_stems.zip","08_endless_glow_stems.zip","09_awake_stems.zip","10_reclaimed_stems.zip","11_the_wreckage_stems.zip","12_read_stems.zip","13_come_home_stems.zip","14_changed_the_lock_stems.zip","15_down_the_front_stems.zip","16_whole_stems.zip","17_enough_stems.zip","18_open_sky_stems.zip","19_all_of_me_stems.zip","20_better_days_stems.zip"]}
2 changes: 1 addition & 1 deletion public/vault/data.enc.json

Large diffs are not rendered by default.

20 changes: 6 additions & 14 deletions scripts/vault-encrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,15 @@ if (!key) throw new Error("VAULT_KEY missing from .env.vault");
const analysis = JSON.parse(readFileSync("vault-private/vault-data.json", "utf8"));
const prompts = readFileSync("vault-private/error_404_Archive_404_remix_prompts.md", "utf8");

// Stem zips on the private release: one per track, and one per chapter for "all stems"
// (a single 2.4 GB zip is over GitHub's 2 GB limit per release file).
// (the June zip names/sizes in the analysis file are dropped: live sizes come from the release)
const CHAPTERS = ["ORIGIN", "THE FEED", "THE WRECKAGE", "WHOLE"];
// Stem zips on the private release: one per track (WAV + MIDI); "all stems" downloads all 20.
// Even one chapter's zip would pass GitHub's 2 GB limit per release file.
// (live sizes come from the release, so any zip name/size in the analysis file is dropped)
const tracks = analysis.tracks.map((t) => {
const out = { ...t, asset: `${t.n}_${t.slug}_stems.zip` };
delete out.zip;
return out;
});
const chapters = CHAPTERS.map((name, i) => ({
ch: i + 1,
name,
asset: `ARCHIVE_404_stems_0${i + 1}_${name.toLowerCase().replace(/ /g, "_")}.zip`,
}));
const payload = { tracks, chapters, prompts };
const payload = { tracks, prompts };

// data: the browser derives the same key from what the visitor types (WebCrypto PBKDF2) and decrypts
const salt = randomBytes(16);
Expand Down Expand Up @@ -68,12 +62,10 @@ writeFileSync(
"netlify/vault-proof.json",
JSON.stringify({
proof: createHash("sha256").update(proof).digest("hex"),
assets: [...tracks.map((t) => t.asset), ...chapters.map((ch) => ch.asset)],
assets: tracks.map((t) => t.asset),
}) + "\n",
);
console.log(
`Locked ${tracks.length} tracks and ${prompts.length} characters of prompts with the access key.`,
);
console.log(
"Stem zip names for the private release:\n " + [...tracks, ...chapters].map((x) => x.asset).join("\n "),
);
console.log("Stem zip names for the private release:\n " + tracks.map((x) => x.asset).join("\n "));
8 changes: 3 additions & 5 deletions src/vault/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ function rowHTML(t) {
<div class="boxbar"><span class="count" data-lcount></span><span class="kitbar"><button class="gbtn" data-copy-lyrics>COPY LYRICS</button><button class="holo" data-kit>⧉ COPY REMIX KIT</button></span></div>
</div>
<div class="tab" data-pane="stems">
<div class="stems">${t.stems.map((s) => `<div class="stem"><span>${s.name.toUpperCase()}</span><span class="fmt">${s.wav ? `<button data-toast="${s.name} WAV (MOCKUP)">WAV</button>` : ""}${s.mid ? `<button data-toast="${s.name} MIDI (MOCKUP)">MIDI</button>` : ""}</span></div>`).join("")}</div>
<div class="stems">${t.stems.map((s) => `<div class="stem"><span>${s.name.toUpperCase()}</span><span class="fmt">${s.wav ? "<i>WAV</i>" : ""}${s.mid ? "<i>MIDI</i>" : ""}</span></div>`).join("")}</div>
<div class="boxbar"><span class="count">${esc(t.asset.toUpperCase())} · WAV + MIDI${STEMS_READY ? "" : " · UPLOADING SOON"}</span><button class="holo" data-dl="${t.slug}">↓ DOWNLOAD STEMS${SIZES[t.asset] ? " · " + mb(SIZES[t.asset]) : ""}</button></div>
</div>
<div class="tab" data-pane="analysis"><div class="an">
Expand Down Expand Up @@ -815,7 +815,7 @@ async function download(slug) {
const t = slug === "all" ? null : TRACKS.find((x) => x.slug === slug);
const files = t
? [{ asset: t.asset, label: `${t.n}_${t.title}_STEMS.ZIP` }]
: CHAPTERS.map((c) => ({ asset: c.asset, label: c.asset.toUpperCase() }));
: TRACKS.map((x) => ({ asset: x.asset, label: `${x.n}_${x.title}_STEMS.ZIP` })); // one zip per track: a chapter would pass GitHub's 2 GB per file
clearTimeout(xHide);
const X = $("#xfer"),
log = $("#xLog");
Expand All @@ -826,7 +826,7 @@ async function download(slug) {
$("#xState").style.color = c;
};
const total = files.reduce((n, f) => n + (SIZES[f.asset] || 0), 0);
$("#xName").textContent = t ? files[0].label : `ARCHIVE_404 · ALL STEMS · ${files.length} CHAPTER ZIPS`;
$("#xName").textContent = t ? files[0].label : `ARCHIVE_404 · ALL STEMS · ${files.length} ZIPS`;
$("#xBar").style.width = "0";
$("#xSize").textContent = total ? mb(total) : "—";
$("#xSpeed").textContent = "—";
Expand Down Expand Up @@ -1165,7 +1165,6 @@ addEventListener("resize", drawRuler);
const SESSION = "e404-vault";
let SIZES = {},
STEMS_READY = false,
CHAPTERS = [],
PROOF = "",
loaded = false,
sealed = null;
Expand Down Expand Up @@ -1245,7 +1244,6 @@ function applyData(d) {
if (loaded) return;
loaded = true;
TRACKS = d.tracks;
CHAPTERS = d.chapters;
parsePrompts(d.prompts);
$("#stemTotal").textContent = "SOON";
$("#allSize").textContent = "SOON";
Expand Down
10 changes: 4 additions & 6 deletions src/vault/vault.css
Original file line number Diff line number Diff line change
Expand Up @@ -1553,16 +1553,14 @@ details.fold[open] summary::after {
display: flex;
gap: 4px;
}
.stem .fmt button {
/* what each stem comes as (both are in the track's zip) */
.stem .fmt i {
font-style: normal;
font-size: 9px;
letter-spacing: 0.14em;
padding: 6px 7px;
border: 1px solid var(--hair);
color: var(--t2);
}
.stem .fmt button:hover {
border-color: var(--cyan);
color: var(--cyan);
color: var(--t3);
}
.an {
display: grid;
Expand Down
Loading