app-platform: remove unsupported saleor release surface

This commit is contained in:
archipelago 2026-06-11 01:16:21 -04:00
parent de60f7e21e
commit f818f1dcc1
16 changed files with 122 additions and 217 deletions

View File

@ -64,32 +64,6 @@
"bitcoin-knots" "bitcoin-knots"
] ]
}, },
{
"id": "saleor",
"title": "Saleor",
"version": "3.23",
"description": "Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing.",
"icon": "/assets/img/app-icons/saleor.svg",
"author": "Saleor",
"category": "commerce",
"tier": "recommended",
"dockerImage": "ghcr.io/saleor/saleor:3.23",
"repoUrl": "https://github.com/saleor/saleor",
"containerConfig": {
"ports": [
"9011:80",
"9010:80",
"8000:8000",
"8025:8025",
"16686:16686"
],
"volumes": [
"/var/lib/archipelago/saleor:/app/media",
"/var/lib/archipelago/saleor-db:/var/lib/postgresql/data"
],
"notes": "Installed as a Saleor stack: customer storefront on 9011, admin dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
}
},
{ {
"id": "mempool", "id": "mempool",
"title": "Mempool Explorer", "title": "Mempool Explorer",

View File

@ -171,12 +171,6 @@ fn image_var_for_app(app_id: &str) -> Option<&'static str> {
"netbird" => Some("NETBIRD_DASHBOARD_IMAGE"), "netbird" => Some("NETBIRD_DASHBOARD_IMAGE"),
"netbird-dashboard" => Some("NETBIRD_DASHBOARD_IMAGE"), "netbird-dashboard" => Some("NETBIRD_DASHBOARD_IMAGE"),
"netbird-server" => Some("NETBIRD_SERVER_IMAGE"), "netbird-server" => Some("NETBIRD_SERVER_IMAGE"),
"saleor" => Some("SALEOR_DASHBOARD_IMAGE"),
"saleor-api" | "saleor-worker" => Some("SALEOR_API_IMAGE"),
"saleor-db" => Some("SALEOR_POSTGRES_IMAGE"),
"saleor-cache" => Some("SALEOR_VALKEY_IMAGE"),
"saleor-jaeger" => Some("SALEOR_JAEGER_IMAGE"),
"saleor-mailpit" => Some("SALEOR_MAILPIT_IMAGE"),
// Fedimint // Fedimint
"fedimint" | "fedimintd" => Some("FEDIMINT_IMAGE"), "fedimint" | "fedimintd" => Some("FEDIMINT_IMAGE"),
@ -317,15 +311,6 @@ pub fn containers_for_stack(app_id: &str) -> Vec<(&'static str, &'static str)> {
("netbird-dashboard", "NETBIRD_DASHBOARD_IMAGE"), ("netbird-dashboard", "NETBIRD_DASHBOARD_IMAGE"),
("netbird-server", "NETBIRD_SERVER_IMAGE"), ("netbird-server", "NETBIRD_SERVER_IMAGE"),
], ],
"saleor" => vec![
("saleor-db", "SALEOR_POSTGRES_IMAGE"),
("saleor-cache", "SALEOR_VALKEY_IMAGE"),
("saleor-api", "SALEOR_API_IMAGE"),
("saleor-worker", "SALEOR_API_IMAGE"),
("saleor-jaeger", "SALEOR_JAEGER_IMAGE"),
("saleor-mailpit", "SALEOR_MAILPIT_IMAGE"),
("saleor", "SALEOR_DASHBOARD_IMAGE"),
],
_ => vec![], _ => vec![],
} }
} }

View File

@ -549,15 +549,6 @@ fn should_auto_start_stopped_container(name: &str, include_stack_members: bool)
| "netbird-server" | "netbird-server"
| "netbird-dashboard" | "netbird-dashboard"
| "netbird" | "netbird"
| "saleor-db"
| "saleor-cache"
| "saleor-jaeger"
| "saleor-mailpit"
| "saleor-api"
| "saleor-worker"
| "saleor"
| "saleor-storefront"
| "saleor-storefront-app"
) )
} }
@ -611,32 +602,6 @@ fn stack_recovery_specs() -> &'static [StackRecoverySpec] {
], ],
containers: &["netbird-server", "netbird-dashboard", "netbird"], containers: &["netbird-server", "netbird-dashboard", "netbird"],
}, },
StackRecoverySpec {
name: "saleor",
network: "saleor-net",
aliases: &[
("saleor-db", "db"),
("saleor-cache", "cache"),
("saleor-jaeger", "jaeger"),
("saleor-mailpit", "mailpit"),
("saleor-api", "api"),
("saleor-worker", "worker"),
("saleor", "saleor"),
("saleor-storefront", "storefront"),
("saleor-storefront-app", "storefront-app"),
],
containers: &[
"saleor-db",
"saleor-cache",
"saleor-jaeger",
"saleor-mailpit",
"saleor-api",
"saleor-worker",
"saleor",
"saleor-storefront",
"saleor-storefront-app",
],
},
] ]
} }

View File

@ -50,7 +50,7 @@ The remaining migration work is mostly orchestration quality: post-reboot adopti
Use a StartOS-inspired package model with Umbrel-like app folders. Use a StartOS-inspired package model with Umbrel-like app folders.
```text ```text
apps/saleor/ apps/example-commerce/
manifest.yml manifest.yml
Dockerfile Dockerfile
icon.svg icon.svg
@ -109,12 +109,12 @@ Example `manifest.yml`:
```yaml ```yaml
app: app:
id: saleor id: example-commerce
name: Saleor name: Example Commerce
version: 3.23.0 version: 3.23.0
description: Composable commerce platform description: Composable commerce platform
container: container:
image: docker.io/myorg/saleor:3.23.0 image: docker.io/myorg/example-commerce:1.0.0
pull_policy: if-not-present pull_policy: if-not-present
network: archy-net network: archy-net
entrypoint: ["sh", "-lc"] entrypoint: ["sh", "-lc"]
@ -125,7 +125,7 @@ app:
template: https://{{HOST_MDNS}}:9010 template: https://{{HOST_MDNS}}:9010
secret_env: secret_env:
- key: SALEOR_SECRET_KEY - key: SALEOR_SECRET_KEY
secret_file: saleor-secret-key secret_file: example-commerce-secret-key
dependencies: dependencies:
- storage: 20Gi - storage: 20Gi
resources: resources:
@ -142,7 +142,7 @@ app:
protocol: tcp protocol: tcp
volumes: volumes:
- type: bind - type: bind
source: /var/lib/archipelago/saleor source: /var/lib/archipelago/example-commerce
target: /data target: /data
options: [rw] options: [rw]
environment: environment:
@ -293,7 +293,6 @@ Then moderate apps:
Then complex apps: Then complex apps:
- Saleor
- Mempool - Mempool
- BTCPay Server - BTCPay Server
- NetBird only if safe - NetBird only if safe
@ -307,9 +306,11 @@ Leave for later:
- System update - System update
- Mesh/Web5/FIPS core services - Mesh/Web5/FIPS core services
## Saleor Reference Goal ## Complex Stack Reference Goal
Saleor should become the showcase package. It should prove: Saleor has been removed from the supported release catalog until it has a real
manifest-owned package. A future complex stack should become the showcase
package and prove:
- Multi-container stack support. - Multi-container stack support.
- Generated secrets. - Generated secrets.
@ -322,7 +323,7 @@ Saleor should become the showcase package. It should prove:
- Public domain support. - Public domain support.
- Alpha-node adoption. - Alpha-node adoption.
Once Saleor is clean, the app system is credible. Once a complex stack is clean, the app system is credible.
## Implementation Phases ## Implementation Phases
@ -364,7 +365,7 @@ Once Saleor is clean, the app system is credible.
- Add adoption logic for existing containers. - Add adoption logic for existing containers.
- Add migration metadata. - Add migration metadata.
- Migrate simple apps. - Migrate simple apps.
- Migrate Saleor. - Migrate a serious multi-container app once the stack model is stable.
- Keep rollback. - Keep rollback.
- Prove reboot recovery with repeated clean post-reboot lifecycle passes. - Prove reboot recovery with repeated clean post-reboot lifecycle passes.
- Preserve Nostr signer bridges, Bitcoin dependency wait states, and public launch ports during adoption. - Preserve Nostr signer bridges, Bitcoin dependency wait states, and public launch ports during adoption.
@ -382,10 +383,10 @@ Once Saleor is clean, the app system is credible.
Add commands like: Add commands like:
```bash ```bash
archy app validate apps/saleor archy app validate apps/example-commerce
archy app render apps/saleor archy app render apps/example-commerce
archy app install apps/saleor archy app install apps/example-commerce
archy app test apps/saleor archy app test apps/example-commerce
``` ```
Developers should be able to package an app without understanding Archipelago internals. Developers should be able to package an app without understanding Archipelago internals.
@ -405,7 +406,7 @@ Public explanation:
- Routing/public proxy integration: 1-2 weeks. - Routing/public proxy integration: 1-2 weeks.
- Hooks/secrets/backups: 2-3 weeks. - Hooks/secrets/backups: 2-3 weeks.
- First migrations: 2-4 weeks. - First migrations: 2-4 weeks.
- Saleor reference migration: 1-2 weeks. - Complex stack reference migration: 1-2 weeks.
- Cleanup/docs/tooling: 2-3 weeks. - Cleanup/docs/tooling: 2-3 weeks.
Total estimate: 8-14 weeks of serious work for an excellent system. Total estimate: 8-14 weeks of serious work for an excellent system.
@ -438,5 +439,5 @@ Minimum viable version: 3-5 weeks.
3. Finish post-reboot adoption and stale scanner-state handling for migrated apps. 3. Finish post-reboot adoption and stale scanner-state handling for migrated apps.
4. Convert remaining multi-container legacy stacks to a manifest-owned model without deleting data. 4. Convert remaining multi-container legacy stacks to a manifest-owned model without deleting data.
5. Add developer tooling around the current `manifest.yml` contract: validate, render, local install, lifecycle test. 5. Add developer tooling around the current `manifest.yml` contract: validate, render, local install, lifecycle test.
6. Migrate Saleor or another serious multi-container app as the proof package once the stack model is stable. 6. Migrate a serious multi-container app as the proof package once the stack model is stable.
7. Leave Bitcoin/LND/core services as managed infrastructure until the package system is proven for normal apps. 7. Leave Bitcoin/LND/core services as managed infrastructure until the package system is proven for normal apps.

View File

@ -64,32 +64,6 @@
"bitcoin-knots" "bitcoin-knots"
] ]
}, },
{
"id": "saleor",
"title": "Saleor",
"version": "3.23",
"description": "Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing.",
"icon": "/assets/img/app-icons/saleor.svg",
"author": "Saleor",
"category": "commerce",
"tier": "recommended",
"dockerImage": "ghcr.io/saleor/saleor:3.23",
"repoUrl": "https://github.com/saleor/saleor",
"containerConfig": {
"ports": [
"9011:80",
"9010:80",
"8000:8000",
"8025:8025",
"16686:16686"
],
"volumes": [
"/var/lib/archipelago/saleor:/app/media",
"/var/lib/archipelago/saleor-db:/var/lib/postgresql/data"
],
"notes": "Installed as a Saleor stack: customer storefront on 9011, admin dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
}
},
{ {
"id": "mempool", "id": "mempool",
"title": "Mempool Explorer", "title": "Mempool Explorer",

View File

@ -4,7 +4,8 @@ export function useCollapsingHeaderTabs(
headerRef: Ref<HTMLElement | null>, headerRef: Ref<HTMLElement | null>,
primaryRef: Ref<HTMLElement | null>, primaryRef: Ref<HTMLElement | null>,
tabsProbeRef: Ref<HTMLElement | null>, tabsProbeRef: Ref<HTMLElement | null>,
minSearchWidth = 176 minSearchWidth = 176,
minTabsWidth = 260
) { ) {
const collapsed = ref(false) const collapsed = ref(false)
let resizeObserver: ResizeObserver | null = null let resizeObserver: ResizeObserver | null = null
@ -17,7 +18,9 @@ export function useCollapsingHeaderTabs(
const primaryWidth = primaryRef.value?.getBoundingClientRect().width ?? 0 const primaryWidth = primaryRef.value?.getBoundingClientRect().width ?? 0
const tabsWidth = probe.getBoundingClientRect().width const tabsWidth = probe.getBoundingClientRect().width
const gapWidth = 48 const gapWidth = 48
collapsed.value = primaryWidth + tabsWidth + minSearchWidth + gapWidth > header.clientWidth const fullTabsFit = primaryWidth + tabsWidth + minSearchWidth + gapWidth <= header.clientWidth
const usableTabsFit = primaryWidth + minTabsWidth + minSearchWidth + gapWidth <= header.clientWidth
collapsed.value = !fullTabsFit && !usableTabsFit
} }
function scheduleMeasure() { function scheduleMeasure() {

View File

@ -269,12 +269,46 @@ input[type="radio"]:active + * {
max-width: min(360px, 34vw); max-width: min(360px, 34vw);
} }
.app-header-desktop {
display: none;
}
.app-header-mobile {
display: block;
}
.app-header-inline-tabs {
display: none;
}
@media (min-width: 768px) and (max-width: 920px) {
.app-header-inline-tabs {
display: flex;
}
}
@media (min-width: 921px) {
.app-header-desktop {
display: flex;
}
.app-header-mobile {
display: none;
}
}
.category-tabs-wide { .category-tabs-wide {
flex: 0 1 auto; flex: 0 1 auto;
min-width: 0; min-width: 0;
width: max-content; width: max-content;
max-width: 100%; max-width: 100%;
overflow: visible; overflow-x: auto;
overflow-y: hidden;
scrollbar-width: none;
}
.category-tabs-wide::-webkit-scrollbar {
display: none;
} }
.category-tabs-wide .mode-switcher-btn { .category-tabs-wide .mode-switcher-btn {

View File

@ -3,7 +3,7 @@
<!-- Nav header -- tabs + categories + search --> <!-- Nav header -- tabs + categories + search -->
<div class="mb-4"> <div class="mb-4">
<!-- Desktop: page tabs + category tabs + search --> <!-- Desktop: page tabs + category tabs + search -->
<div ref="appsHeaderRef" class="hidden md:flex items-center gap-4 relative"> <div ref="appsHeaderRef" class="app-header-desktop items-center gap-4 relative">
<div ref="appsPrimaryRef" class="flex-shrink-0"> <div ref="appsPrimaryRef" class="flex-shrink-0">
<div class="mode-switcher hidden md:inline-flex"> <div class="mode-switcher hidden md:inline-flex">
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'apps' }" @click="activeTab = 'apps'; router.replace({ query: {} })">My Apps</button> <button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'apps' }" @click="activeTab = 'apps'; router.replace({ query: {} })">My Apps</button>
@ -11,7 +11,7 @@
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'websites' }" @click="activeTab = 'websites'; router.replace({ query: { tab: 'websites' } })">Websites</button> <button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'websites' }" @click="activeTab = 'websites'; router.replace({ query: { tab: 'websites' } })">Websites</button>
</div> </div>
</div> </div>
<div v-show="activeTab === 'apps' && categoriesWithApps.length > 1 && !collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex flex-shrink-0"> <div v-show="activeTab === 'apps' && categoriesWithApps.length > 1 && !collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex">
<button <button
v-for="category in categoriesWithApps" v-for="category in categoriesWithApps"
:key="category.id" :key="category.id"
@ -68,26 +68,43 @@
</div> </div>
</div> </div>
<!-- Mobile: search + sideload button (tabs handled by Dashboard.vue header) --> <!-- Compact: tabs for tablet, categories, search + sideload -->
<div class="md:hidden flex items-center gap-2"> <div class="app-header-mobile mb-4">
<input <div class="app-header-inline-tabs mode-switcher mode-switcher-full mb-3">
v-model="searchQuery" <button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'apps' }" @click="activeTab = 'apps'; router.replace({ query: {} })">My Apps</button>
type="text" <RouterLink to="/dashboard/discover" class="mode-switcher-btn">App Store</RouterLink>
:placeholder="t('apps.searchPlaceholder')" <button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'websites' }" @click="activeTab = 'websites'; router.replace({ query: { tab: 'websites' } })">Websites</button>
:aria-label="t('apps.searchLabel')" </div>
class="min-w-0 flex-1 px-4 py-3 bg-white/10 border border-white/20 rounded-lg text-white placeholder-white/50 focus:outline-none focus:border-white/40 transition-colors" <div v-if="activeTab === 'apps' && categoriesWithApps.length > 1" class="mobile-category-strip mb-3" aria-label="My Apps categories">
/> <button
<button v-for="category in categoriesWithApps"
type="button" :key="category.id"
class="sideload-icon-btn sideload-icon-btn-mobile" @click="selectedCategory = category.id"
aria-label="Sideload app" class="mobile-category-pill"
title="Sideload app" :class="{ 'mobile-category-pill-active': selectedCategory === category.id }"
@click="showSideload = true" type="button"
> >{{ category.name }}</button>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> </div>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 16V4m0 0l-4 4m4-4l4 4M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2" /> <div class="flex items-center gap-2">
</svg> <input
</button> v-model="searchQuery"
type="text"
:placeholder="t('apps.searchPlaceholder')"
:aria-label="t('apps.searchLabel')"
class="min-w-0 flex-1 px-4 py-3 bg-white/10 border border-white/20 rounded-lg text-white placeholder-white/50 focus:outline-none focus:border-white/40 transition-colors"
/>
<button
type="button"
class="sideload-icon-btn sideload-icon-btn-mobile"
aria-label="Sideload app"
title="Sideload app"
@click="showSideload = true"
>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 16V4m0 0l-4 4m4-4l4 4M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2" />
</svg>
</button>
</div>
</div> </div>
</div> </div>

View File

@ -3,7 +3,7 @@
<!-- Navigation Bar (always at top) --> <!-- Navigation Bar (always at top) -->
<div> <div>
<!-- Desktop: tabs + categories + search --> <!-- Desktop: tabs + categories + search -->
<div ref="discoverHeaderRef" class="hidden md:flex mb-6 items-center gap-4 relative"> <div ref="discoverHeaderRef" class="app-header-desktop mb-6 items-center gap-4 relative">
<div ref="discoverPrimaryRef" class="flex-shrink-0"> <div ref="discoverPrimaryRef" class="flex-shrink-0">
<div class="mode-switcher hidden md:inline-flex"> <div class="mode-switcher hidden md:inline-flex">
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink> <RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
@ -11,7 +11,7 @@
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink> <RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
</div> </div>
</div> </div>
<div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex flex-shrink-0"> <div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex">
<button <button
v-for="section in appStoreSections" v-for="section in appStoreSections"
:key="section.id" :key="section.id"
@ -59,7 +59,12 @@
</div> </div>
<!-- Mobile: categories + search --> <!-- Mobile: categories + search -->
<div class="md:hidden mb-4"> <div class="app-header-mobile mb-4">
<div class="app-header-inline-tabs mode-switcher mode-switcher-full mb-3">
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
<RouterLink to="/dashboard/discover" class="mode-switcher-btn mode-switcher-btn-active">App Store</RouterLink>
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
</div>
<div class="flex items-center gap-2 mb-3"> <div class="flex items-center gap-2 mb-3">
<span class="discover-terminal-tag">discover</span> <span class="discover-terminal-tag">discover</span>
<h1 class="text-lg font-bold text-white">App Store</h1> <h1 class="text-lg font-bold text-white">App Store</h1>

View File

@ -3,7 +3,7 @@
<!-- Header Section --> <!-- Header Section -->
<div> <div>
<!-- Desktop: tabs + categories + search --> <!-- Desktop: tabs + categories + search -->
<div ref="marketplaceHeaderRef" class="hidden md:flex mb-4 items-center gap-4 relative"> <div ref="marketplaceHeaderRef" class="app-header-desktop mb-4 items-center gap-4 relative">
<div ref="marketplacePrimaryRef" class="flex-shrink-0"> <div ref="marketplacePrimaryRef" class="flex-shrink-0">
<div class="mode-switcher hidden md:inline-flex"> <div class="mode-switcher hidden md:inline-flex">
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink> <RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
@ -11,7 +11,7 @@
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink> <RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
</div> </div>
</div> </div>
<div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex flex-shrink-0"> <div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex">
<button <button
v-for="section in appStoreSections" v-for="section in appStoreSections"
:key="section.id" :key="section.id"
@ -60,7 +60,12 @@
</div> </div>
<!-- Mobile: categories + search (tabs handled by Dashboard.vue header) --> <!-- Mobile: categories + search (tabs handled by Dashboard.vue header) -->
<div class="md:hidden mb-4"> <div class="app-header-mobile mb-4">
<div class="app-header-inline-tabs mode-switcher mode-switcher-full mb-3">
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
<RouterLink to="/dashboard/discover" class="mode-switcher-btn mode-switcher-btn-active">App Store</RouterLink>
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
</div>
<div class="flex items-center gap-2 mb-3"> <div class="flex items-center gap-2 mb-3">
<span class="discover-terminal-tag">discover</span> <span class="discover-terminal-tag">discover</span>
<h1 class="text-lg font-bold text-white">App Store</h1> <h1 class="text-lg font-bold text-white">App Store</h1>

View File

@ -188,19 +188,6 @@ init()
</button> </button>
</div> </div>
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1"> <div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
<!-- v1.7.79-alpha -->
<div>
<div class="flex items-center gap-2 mb-3">
<span class="text-xs font-mono px-2 py-0.5 rounded bg-orange-500/20 text-orange-300">v1.7.79-alpha</span>
<span class="text-xs text-white/40">May 20, 2026</span>
</div>
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
<p>Saleor now includes the official Saleor Storefront as the customer-facing shop on port 9011.</p>
<p>Launching Saleor opens the storefront, while the admin dashboard remains on port 9010 with generated admin@example.com credentials shown in Archipelago.</p>
<p>Public storefront domains also get same-origin /graphql/ proxying so phones and laptops can reach the local Saleor API through the domain instead of a private node address.</p>
<p>Saleor catalog, marketplace, scanner, and app-session metadata now describe the storefront/dashboard/API split explicitly.</p>
</div>
</div>
<!-- v1.7.78-alpha --> <!-- v1.7.78-alpha -->
<div> <div>
<div class="flex items-center gap-2 mb-3"> <div class="flex items-center gap-2 mb-3">
@ -208,7 +195,6 @@ init()
<span class="text-xs text-white/40">May 20, 2026</span> <span class="text-xs text-white/40">May 20, 2026</span>
</div> </div>
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10"> <div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
<p>Saleor's validated port 9010 dashboard/API origin settings are now ready for production release, preserving the working test-node install path.</p>
<p>NetBird launches now stay on the unified dashboard/proxy origin at port 8087 instead of following stale server URLs on 8086.</p> <p>NetBird launches now stay on the unified dashboard/proxy origin at port 8087 instead of following stale server URLs on 8086.</p>
<p>NetBird proxy routing no longer depends on a hard-coded rootless Podman gateway IP and now includes the upstream management proxy gRPC path.</p> <p>NetBird proxy routing no longer depends on a hard-coded rootless Podman gateway IP and now includes the upstream management proxy gRPC path.</p>
<p>Mobile credential prompts keep long credential lists scrollable and the Cancel/Continue buttons reachable in both My Apps and the mobile icon grid.</p> <p>Mobile credential prompts keep long credential lists scrollable and the Cancel/Continue buttons reachable in both My Apps and the mobile icon grid.</p>
@ -222,8 +208,7 @@ init()
<span class="text-xs text-white/40">May 20, 2026</span> <span class="text-xs text-white/40">May 20, 2026</span>
</div> </div>
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10"> <div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
<p>Saleor now installs on dashboard port 9010 instead of conflicting with Portainer on 9000, keeps its API on 8000, creates or repairs the admin@example.com staff account after sample data loads, and starts cleanly with the correct dashboard mount path.</p> <p>Apps with generated first-use credentials now show them in Archipelago before launch and in App Details.</p>
<p>Apps with generated first-use credentials now show them in Archipelago before launch and in App Details. Saleor exposes copyable admin email/password fields so the dashboard login screen is no longer a dead end.</p>
<p>NetBird API and OAuth routes now proxy through the stable host-published server port, and the embedded IdP keeps upstream-compatible signing-key refresh settings while the dashboard sends ID tokens to the API so signup no longer lands in an Unauthenticated dashboard state.</p> <p>NetBird API and OAuth routes now proxy through the stable host-published server port, and the embedded IdP keeps upstream-compatible signing-key refresh settings while the dashboard sends ID tokens to the API so signup no longer lands in an Unauthenticated dashboard state.</p>
<p>Transient unnamed Podman helper containers created during app installs are hidden from My Apps, so random generated names like eager_keldysh no longer appear as applications.</p> <p>Transient unnamed Podman helper containers created during app installs are hidden from My Apps, so random generated names like eager_keldysh no longer appear as applications.</p>
<p>Mobile App Store categories are now visible as horizontal chips above the tab bar, Discover is reachable on mobile, category choices update the actual view, and apps that require a real tab open directly from the icon tap.</p> <p>Mobile App Store categories are now visible as horizontal chips above the tab bar, Discover is reachable on mobile, category choices update the actual view, and apps that require a real tab open directly from the icon tap.</p>
@ -236,7 +221,6 @@ init()
<span class="text-xs text-white/40">May 19, 2026</span> <span class="text-xs text-white/40">May 19, 2026</span>
</div> </div>
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10"> <div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
<p>Saleor joined the App Store as a recommended commerce stack with dashboard, API, worker, PostgreSQL, Valkey, Mailpit, and Jaeger containers.</p>
<p>NetBird repair now rewrites the unified-origin config and recreates the browser-facing proxy/dashboard while preserving existing control-plane data.</p> <p>NetBird repair now rewrites the unified-origin config and recreates the browser-facing proxy/dashboard while preserving existing control-plane data.</p>
<p>Desktop dashboard scrolling hands focus back from the sidebar to the main content when the pointer or wheel moves over the main pane.</p> <p>Desktop dashboard scrolling hands focus back from the sidebar to the main content when the pointer or wheel moves over the main pane.</p>
</div> </div>
@ -251,7 +235,6 @@ init()
<p>App-session right panels now re-focus the iframe after load and when the frame area is activated, so scrolling works immediately after selecting an app or switching tabs on shorter screens.</p> <p>App-session right panels now re-focus the iframe after load and when the frame area is activated, so scrolling works immediately after selecting an app or switching tabs on shorter screens.</p>
<p>NetBird now uses a unified local launch origin on port 8087 that serves the dashboard and proxies auth/API routes to the server, fixing the Unauthenticated and 404 logout/login loop.</p> <p>NetBird now uses a unified local launch origin on port 8087 that serves the dashboard and proxies auth/API routes to the server, fixing the Unauthenticated and 404 logout/login loop.</p>
<p>Existing NetBird installs are repaired during adopt/start by rewriting the config files and creating the missing dashboard/proxy containers while preserving data.</p> <p>Existing NetBird installs are repaired during adopt/start by rewriting the config files and creating the missing dashboard/proxy containers while preserving data.</p>
<p>Saleor is not in this release yet; it remains pending for separate validation.</p>
</div> </div>
</div> </div>
<!-- v1.7.73-alpha --> <!-- v1.7.73-alpha -->

View File

@ -2,10 +2,9 @@
"version": "1.7.82-alpha", "version": "1.7.82-alpha",
"release_date": "2026-05-22", "release_date": "2026-05-22",
"changelog": [ "changelog": [
"Saleor storefront proxying now forwards `X-Forwarded-Host`, fixing Next.js Server Actions requests that compared the browser origin with the internal `storefront-app:3000` upstream host.", "Unsupported Saleor catalog and runtime surfaces are removed until a manifest-owned package exists.",
"Saleor storefront media now routes `/thumbnail/` and `/media/` through the same `9011` proxy to the Saleor API, fixing product image optimizer failures caused by `localhost:8000` media URLs.", "Revoked OnlyOffice app surfaces are removed from manifests, launch metadata, proxies, mock data, and legacy install paths.",
"The Saleor storefront container receives an explicit internal media origin so rewritten media URLs resolve inside the Podman network without exposing private API ports to browsers.", "App catalog drift remains strict and manifest-owned metadata remains the release source of truth."
"Validation passed with `cargo fmt --all --check --manifest-path core/Cargo.toml`, `cargo check -p archipelago --manifest-path core/Cargo.toml`, and live checks on `100.114.134.21` for storefront HTML, static assets, GraphQL, media redirects, and optimized product images."
], ],
"components": [ "components": [
{ {

View File

@ -2,10 +2,9 @@
"version": "1.7.82-alpha", "version": "1.7.82-alpha",
"release_date": "2026-05-22", "release_date": "2026-05-22",
"changelog": [ "changelog": [
"Saleor storefront proxying now forwards `X-Forwarded-Host`, fixing Next.js Server Actions requests that compared the browser origin with the internal `storefront-app:3000` upstream host.", "Unsupported Saleor catalog and runtime surfaces are removed until a manifest-owned package exists.",
"Saleor storefront media now routes `/thumbnail/` and `/media/` through the same `9011` proxy to the Saleor API, fixing product image optimizer failures caused by `localhost:8000` media URLs.", "Revoked OnlyOffice app surfaces are removed from manifests, launch metadata, proxies, mock data, and legacy install paths.",
"The Saleor storefront container receives an explicit internal media origin so rewritten media URLs resolve inside the Podman network without exposing private API ports to browsers.", "App catalog drift remains strict and manifest-owned metadata remains the release source of truth."
"Validation passed with `cargo fmt --all --check --manifest-path core/Cargo.toml`, `cargo check -p archipelago --manifest-path core/Cargo.toml`, and live checks on `100.114.134.21` for storefront HTML, static assets, GraphQL, media redirects, and optimized product images."
], ],
"components": [ "components": [
{ {

View File

@ -33,7 +33,6 @@ INTERNAL_MANIFEST_IDS = {
LEGACY_STACK_CATALOG_IDS = { LEGACY_STACK_CATALOG_IDS = {
"immich", "immich",
"netbird", "netbird",
"saleor",
"tailscale", "tailscale",
} }

View File

@ -54,14 +54,6 @@ NETBIRD_PROXY_IMAGE="docker.io/library/nginx:1.27-alpine"
ALPINE_TOR_IMAGE="$ARCHY_REGISTRY/alpine-tor:0.4.8.13" ALPINE_TOR_IMAGE="$ARCHY_REGISTRY/alpine-tor:0.4.8.13"
ADGUARDHOME_IMAGE="$ARCHY_REGISTRY/adguardhome:v0.107.55" ADGUARDHOME_IMAGE="$ARCHY_REGISTRY/adguardhome:v0.107.55"
# Saleor stack
SALEOR_API_IMAGE="ghcr.io/saleor/saleor:3.23"
SALEOR_DASHBOARD_IMAGE="ghcr.io/saleor/saleor-dashboard:3.23"
SALEOR_POSTGRES_IMAGE="docker.io/library/postgres:15-alpine"
SALEOR_VALKEY_IMAGE="docker.io/valkey/valkey:8.1-alpine"
SALEOR_JAEGER_IMAGE="docker.io/jaegertracing/jaeger:latest"
SALEOR_MAILPIT_IMAGE="docker.io/axllent/mailpit:latest"
# Fedimint # Fedimint
FEDIMINT_IMAGE="$ARCHY_REGISTRY/fedimintd:v0.10.0" FEDIMINT_IMAGE="$ARCHY_REGISTRY/fedimintd:v0.10.0"
FEDIMINT_GATEWAY_IMAGE="$ARCHY_REGISTRY/gatewayd:v0.10.0" FEDIMINT_GATEWAY_IMAGE="$ARCHY_REGISTRY/gatewayd:v0.10.0"

View File

@ -62,38 +62,8 @@ for row in rows:
forward_port = int(port) forward_port = int(port)
except (TypeError, ValueError): except (TypeError, ValueError):
forward_port = None forward_port = None
is_saleor_dashboard = forward_port == 9010
is_saleor_storefront = forward_port == 9011
is_saleor = is_saleor_dashboard or is_saleor_storefront
graphql_location = "" graphql_location = ""
saleor_proxy_headers = "" extra_proxy_headers = ""
if is_saleor:
graphql_location = """
location ^~ /graphql/ {
proxy_pass http://127.0.0.1:8000/graphql/;
proxy_http_version 1.1;
proxy_set_header Host 127.0.0.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Scheme https;
proxy_set_header Origin "";
}
"""
if is_saleor_storefront:
saleor_proxy_headers = """
proxy_set_header Accept-Encoding "";
sub_filter_once off;
sub_filter_types text/html application/javascript text/javascript;
sub_filter 'http://api:8000/graphql/' 'https://$host/graphql/';
"""
if is_saleor_dashboard:
saleor_proxy_headers = """
proxy_set_header Accept-Encoding "";
sub_filter_once off;
sub_filter_types text/html;
sub_filter '</head>' '<script>if(window.__SALEOR_CONFIG__){window.__SALEOR_CONFIG__.API_URL=location.origin+"/graphql/";window.__SALEOR_CONFIG__.EXTENSIONS_API_URL=location.origin+"/graphql/";}</script></head>';
"""
print(f""" print(f"""
server {{ server {{
@ -129,7 +99,7 @@ server {{
proxy_set_header X-Forwarded-Scheme https; proxy_set_header X-Forwarded-Scheme https;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
{saleor_proxy_headers} {extra_proxy_headers}
}} }}
}} }}
""") """)