Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a29823d
Default alt arts: one setting for the defaults, final prints per deck…
Yutsa Oct 8, 2026
3066116
Re:Builder: no « Arts alternatifs » switch in the card search
Yutsa Oct 8, 2026
c0e3772
Re:Builder: the brush shows each copy's default faded, places by touc…
Yutsa Oct 8, 2026
94d5872
Remove a stray Playwright run file
Yutsa Oct 8, 2026
fd053b0
Re:Builder: « Regrouper les illustrations » puts a card's prints on o…
Yutsa Oct 8, 2026
f2a654a
Re:Builder brush: the default alt arts show as chosen; a touched copy…
Yutsa Oct 8, 2026
d0dfa47
Re:Builder: the save status before « Regrouper les illustrations », s…
Yutsa Oct 8, 2026
765722e
Re:Builder brush: the illustrations with their 1st, 2nd and 3rd choic…
Yutsa Oct 9, 2026
fafdfad
Re:Builder brush: « Ce que le deck utilise » shows the copies and its…
Yutsa Oct 9, 2026
4be8c2a
Re:Builder brush: the illustration of each card (1ère, 2ème, 3ème car…
Yutsa Oct 9, 2026
f0e4308
Re:Builder brush: the illustrations in the order of their cards, an a…
Yutsa Oct 10, 2026
2ae1879
Re:Builder brush: two steps, the illustrations on a band ending in a …
Yutsa Oct 10, 2026
9d2b6eb
Re:Builder brush: a late family answer keeps the defaults saved since…
Yutsa Oct 10, 2026
dd76238
Re:Builder brush: the cards' illustrations are this deck's only, kept…
Yutsa Oct 10, 2026
672c57e
Brush choices: a deleted deck loses them; no row for a card whose thr…
Yutsa Oct 10, 2026
a0ec13f
Re:Builder brush: the illustrations keep the service's order; a choic…
Yutsa Oct 10, 2026
bca7b26
Re:Builder brush: each card's ribbon in its own place, 1st on the lef…
Yutsa Oct 10, 2026
4748835
Simplify the brush: one deck-delete helper, cleanup by player and dec…
Yutsa Oct 10, 2026
9c8b423
Re:Builder brush: a choice that cannot be saved puts the copies back …
Yutsa Oct 10, 2026
d56ddbc
Keep the « Global » alt-art mode; leaving it writes the defaults in e…
Yutsa Oct 13, 2026
b797208
Alt-art modes: review and simplify
Yutsa Oct 13, 2026
38151e1
Re:Builder brush: three keys above each illustration instead of ribbo…
Yutsa Oct 13, 2026
2f14105
Default alt arts page: one row per card, its cards fanned out, keys a…
Yutsa Oct 13, 2026
68e0946
Alt-art keys: review fixes
Yutsa Oct 13, 2026
fb69b8b
Default alt arts e2e: Fée Clochette (CORE and MUSUBI prints differ)
Yutsa Oct 13, 2026
98e1450
Default alt arts page: full-size keys, wider illustrations, two a row…
Yutsa Oct 13, 2026
ac58173
Ownership mock: the alt-art search lists every card type, as the service
Yutsa Oct 13, 2026
bf46365
Default alt arts page: larger previews, a card opens large on a click
Yutsa Oct 13, 2026
bc1e9db
Keys: a key that can be pressed at full strength, a disabled key flat…
Yutsa Oct 13, 2026
988522a
Default alt arts page: the choices on the left, what decks take on th…
Yutsa Oct 14, 2026
f530f5a
Default alt arts page: the choices' band ends in a chevron into what …
Yutsa Oct 14, 2026
ae79232
Default alt arts page: a card's illustrations on one line that scroll…
Yutsa Oct 14, 2026
85181ea
Default alt arts page: the illustration cut at an edge fades out
Yutsa Oct 14, 2026
01b0b8d
Leaving « Global »: list the decks once, the decks API ignores the page
Yutsa Oct 14, 2026
79814a1
Alt arts in « Global »: one apply-to-deck line a family
Yutsa Oct 14, 2026
62a3cfd
Default alt arts page: on a phone, what decks take is centred under t…
Yutsa Oct 14, 2026
b73255d
Merge origin/preprod into feat/alt-art-defaults
Yutsa Oct 22, 2026
eed52a9
Leaving « Global »: best effort, a deck that cannot be written no lon…
Yutsa Oct 22, 2026
0d06ed9
Re:Builder Aperçu: a skeleton for « Regrouper les illustrations » too…
Yutsa Oct 22, 2026
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ docker compose -f docker-compose.yml -f docker-compose.stack.yml up -d --build -

Site on http://localhost:8080 (`WEB_PORT` to change it), Keycloak users `alice` / `bob` (password `TestPassword1234`), decks API on http://localhost:8001. Playwright: `cd tests/e2e && npm ci && npx playwright test`. CI runs the same on every pull request (`.github/workflows/plugins-ci.yml`). Loading checks (skeletons, layout shifts): `npm run loading` and `npm run loading:timeline -- <screen>` in `tests/e2e` (`AGENTS.md` § Checks).

**Alt arts with the real ownership service.** The stack's digital ownership is a mock (`docker/stack/ownership-mock`). To try the default alt arts with [AlteredOwnership](https://github.com/Altered-Re-Union/AlteredOwnership) itself, built from GitHub (alice and bob own Axiom alt arts and have default alt arts; alice is in « Global » mode, with a deck of plain prints that takes her default alt arts):

```bash
docker compose -f docker-compose.yml -f docker-compose.stack.yml -f docker-compose.ownership.yml up -d --build --wait
```

Sign in again after its first start (the service needs the `read-collection` scope in the site's tokens). Details in `docker-compose.ownership.yml` and `docker/stack/ownership-real/`.

**Like production.** To get the plugins active on https://altered.re and its public content (news, content pages, side menu, footer, fonts, logo, home page text, images):

```bash
Expand Down
5 changes: 5 additions & 0 deletions api/v1/services/proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ function serviceProxySend(string $method, string $url, array $headers, string $b

if ($res === null) serviceProxyReply(502, ['error' => 'service_unreachable', 'service' => $service]);
[$status, $type, $out] = $res;
// A deck deleted: what the site keeps about it goes too (includes/func.alt-arts.php).
if ($service === 'decks' && $method === 'DELETE' && $status >= 200 && $status < 300 && preg_match('#^api/decks/([A-Za-z0-9-]{1,64})$#', $path, $m)) {
require_once dirname(__DIR__, 3) . '/includes/func.alt-arts.php';
altArtForgetDeck($userId, $m[1]);
}
require_once dirname(__DIR__, 3) . '/includes/json-gzip.php';
jsonGzipStart();
http_response_code($status);
Expand Down
100 changes: 100 additions & 0 deletions design-system/css/components/key.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Keys — a row of toggle buttons drawn as keys: raised when off, pressed down and filled when on, flat and faded
* when disabled.
* Used for the 1st, 2nd and 3rd card that take an illustration (alt arts), one row above each illustration.
* <div class="ac-keys" role="group" aria-label="…">
* <button type="button" class="ac-key" aria-pressed="true" aria-label="1ère carte">
* <span class="ac-key__num">1<sup>ère</sup></span><span class="ac-key__word">carte</span>
* </button>
* …
* </div>
* Docs: design-system/docs/components/key.md
*/
.ac-keys {
display: grid;
grid-template-columns: repeat(var(--ac-keys-count, 3), minmax(0, 1fr));
gap: var(--ac-space-1-5);
}
.ac-key {
--ac-key-height: var(--ac-control-lg);
--ac-key-border: 1.5px;
--ac-key-edge: 4px;
box-sizing: border-box;
height: var(--ac-key-height);
min-width: 0;
margin: 0;
padding: 0 var(--ac-space-1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--ac-space-0-5);
border: var(--ac-key-border) solid var(--ac-color-border-control);
border-bottom: var(--ac-key-edge) solid var(--ac-color-border-dashed);
border-radius: var(--ac-radius-control);
background: var(--ac-color-surface);
color: var(--ac-color-text-2);
font-family: var(--ac-font-family);
cursor: pointer;
transition:
opacity var(--ac-duration-fast),
color var(--ac-duration-fast),
border-color var(--ac-duration-fast),
transform var(--ac-duration-fast);
}
.ac-key--sm {
--ac-key-height: var(--ac-control-md);
}
/* Pressed: the key goes down by its edge, filled. */
.ac-key[aria-pressed='true'] {
height: calc(var(--ac-key-height) - var(--ac-key-edge) + var(--ac-key-border));
margin-top: calc(var(--ac-key-edge) - var(--ac-key-border));
border-color: var(--ac-color-primary-strong);
border-bottom-width: var(--ac-key-border);
background: var(--ac-color-primary);
color: var(--ac-color-on-primary);
box-shadow: inset 0 2px 4px var(--ac-color-overlay-label);
opacity: 1;
cursor: default;
}
.ac-key:not([aria-pressed='true']):not(:disabled):active {
transform: translateY(2px);
}
/* Disabled: flat (no edge), no fill, faded: it cannot be pressed. */
.ac-key:disabled:not([aria-pressed='true']) {
border-bottom-width: var(--ac-key-border);
border-color: var(--ac-color-border);
background: transparent;
color: var(--ac-color-text-disabled);
opacity: 0.6;
cursor: not-allowed;
}
.ac-key:focus-visible {
outline: 2px solid var(--ac-color-focus);
outline-offset: 2px;
opacity: 1;
}
@media (hover: hover) {
.ac-key:not([aria-pressed='true']):not(:disabled):hover {
border-color: var(--ac-color-primary);
color: var(--ac-color-primary);
opacity: 1;
transform: translateY(-1px);
}
}
.ac-key__num {
font-size: var(--ac-font-size-body-strong);
font-weight: 800;
line-height: 1;
}
.ac-key__num sup {
font-size: 0.62em;
line-height: 0;
}
.ac-key__word {
font: var(--ac-font-micro);
}
/* A single key with a word only (« Choisir » / « Choisie »). */
.ac-key__label {
font: var(--ac-font-body-strong);
}
1 change: 1 addition & 0 deletions design-system/docs/components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ One page per component family. Each page matches one file of `css/components/` (
| [field.md](field.md) | `field.css` | Field wrapper, label, hint, error, input, textarea, input with icon, select, checkbox / radio, radio card, file input, switch |
| [listbox.md](listbox.md) | `listbox.css`, `js/ac.js` | Select drawn by the design system: search, groups, colour dots |
| [segmented.md](segmented.md) | `segmented.css` | Segmented control |
| [key.md](key.md) | `key.css` | Keys: toggle buttons raised when off, pressed down when on (alt-art cards) |
| [chips.md](chips.md) | `chips.css` | Chip, badge, tag, count, avatar |
| [card.md](card.md) | `card.css` | Card, list, empty state, collapsible |
| [drawer.md](drawer.md) | `drawer.css` | Drawer handle and tab: hide and show a side panel |
Expand Down
57 changes: 57 additions & 0 deletions design-system/docs/components/key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Keys

`css/components/key.css`.

A row of toggle buttons drawn as keys. A key that is off is raised (thick bottom edge); a key that
is on is pressed down and filled in primary; a disabled key is flat and faded. Several keys of a row
can be on at once.

Used for alt arts: above each illustration of a card, its 1st, 2nd and 3rd card. A key on is a
card that takes this illustration; pressing another key gives it that card. A token has a single
key (« Choisir » / « Choisie »).

Use a [segmented control](segmented.md) instead for one choice among a few options, and a
[switch](field.md) for a setting that is on or off.

## Markup

```php
<div class="ac-keys" role="group" aria-label="<?= h(sprintf(t('altarts.cards_of'), $label)) ?>">
<button type="button" class="ac-key" aria-pressed="true" aria-label="1ère carte">
<span class="ac-key__num">1<sup>ère</sup></span><span class="ac-key__word">carte</span>
</button>
<button type="button" class="ac-key" aria-pressed="false" aria-label="2ème carte">
<span class="ac-key__num">2<sup>ème</sup></span><span class="ac-key__word">carte</span>
</button>
<button type="button" class="ac-key" aria-pressed="false" aria-label="3ème carte" disabled>
<span class="ac-key__num">3<sup>ème</sup></span><span class="ac-key__word">carte</span>
</button>
</div>

<div class="ac-keys" style="--ac-keys-count: 1" role="group" aria-label="…">
<button type="button" class="ac-key" aria-pressed="false"><span class="ac-key__label">Choisir</span></button>
</div>
```

| Class / attribute | Role |
|---|---|
| `ac-keys` | Grid of equal keys, `--ac-space-1-5` apart. `--ac-keys-count` sets the number of columns (3 by default). |
| `ac-key` | A key, `--ac-control-lg` tall (52 px in touch density), raised by a 4 px bottom edge in `--ac-color-border-dashed`, text in `--ac-color-text-2`. |
| `ac-key--sm` | Key at `--ac-control-md` (lists with many rows). |
| `aria-pressed="true"` | Pressed down by its edge, `--ac-color-primary` with an inner shadow, full opacity. |
| `:disabled` | Flat (no edge), no fill, `--ac-color-border` and `--ac-color-text-disabled` at 60 % opacity: clearly apart from a key that can be pressed. |
| `ac-key__num` | Number, `--ac-font-size-body-strong`, its `<sup>` (ordinal suffix) at 0.62 em. |
| `ac-key__word` | Word under the number (« carte »), `--ac-font-micro`. |
| `ac-key__label` | Single word instead of number and word (« Choisir »), `--ac-font-body-strong`. |

Hover (pointer devices only): border and text in primary, the key rises by 1 px.
A pressed key goes down by 2 px while the button is held.

## Accessibility

- Real `<button type="button">` with `aria-pressed`, in a `role="group"` named after what the
keys belong to (« Cartes de Illustration 2 »).
- `aria-label` gives the full name (« 1ère carte »): the number and its `<sup>` are read as one
word otherwise.
- Keys are at least `--ac-control-md` tall; use the default size where touch matters.
- The pressed state is not shown by colour alone: the key is also lower and has no edge.
108 changes: 108 additions & 0 deletions docker-compose.ownership.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Local testing of the alt arts with the real AlteredOwnership service (Altered-Re-Union/AlteredOwnership) instead of
# the mock (docker/stack/ownership-mock, which stays the collection API). On top of the full stack:
#
# docker compose -f docker-compose.yml -f docker-compose.stack.yml -f docker-compose.ownership.yml up -d --build --wait
#
# docker/stack/ownership-real/seed.sql gives alice and bob owned alt arts and default alt arts, and alice the « Global »
# mode (to try its switch to « par deck »); seed-decks.php a deck of hers built in that mode and one of bob's;
# keycloak-scopes.sh the `read-collection` scope the service requires in the site's tokens (sign in again after a first
# start). Service: http://localhost:8003 (health: /health). To try the switch again:
# docker compose -f docker-compose.yml -f docker-compose.stack.yml -f docker-compose.ownership.yml run --rm ownership-seed
# docker compose -f docker-compose.yml -f docker-compose.stack.yml -f docker-compose.ownership.yml run --rm alice-decks
services:
web:
volumes:
- ./docker/stack/ownership-real/config.php:/var/www/html/config.local.php:ro
depends_on:
ownership-seed:
condition: service_completed_successfully

ownership-db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ownership
POSTGRES_PASSWORD: ownership
POSTGRES_DB: ownershipdb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ownership -d ownershipdb"]
interval: 3s
timeout: 3s
retries: 30

ownership-redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 3s
timeout: 3s
retries: 30

ownership-real:
# Pinned: bump the commit to follow the service.
image: alteredcore-stack-ownership
build:
context: https://github.com/Altered-Re-Union/AlteredOwnership.git#41e6248e643ccdb1161775cdec921441a8db91ec
dockerfile: build/Dockerfile
target: app
environment:
# Development: plain HTTP to Keycloak, /health mapped. The schema and the alt-art catalog come from its migrations.
ASPNETCORE_ENVIRONMENT: Development
ConnectionStrings__ownershipdb: Host=ownership-db;Database=ownershipdb;Username=ownership;Password=ownership
ConnectionStrings__cache: ownership-redis:6379
Keycloak__Authority: http://auth.altered.local.gd:18080/realms/players
Keycloak__ClientId: main-site
Keycloak__ClientSecret: dev-main-site-secret
ExternalHosts__AuthBase: http://auth.altered.local.gd:18080
ports:
- "127.0.0.1:8003:8080"
depends_on:
ownership-db:
condition: service_healthy
ownership-redis:
condition: service_healthy
keycloak:
condition: service_healthy
healthcheck:
# The image has no curl: HTTP over bash.
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/8080 && printf 'GET /health HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && grep -q 'Healthy' <&3"]
interval: 5s
timeout: 5s
retries: 60

keycloak-scopes:
image: quay.io/keycloak/keycloak:26.0
entrypoint: ["/bin/bash", "/setup/keycloak-scopes.sh"]
environment:
# kcadm is a plain JVM: JDK 21 dies with SIGILL on recent Apple Silicon (SVE), as the Keycloak service.
JAVA_TOOL_OPTIONS: "-XX:+IgnoreUnrecognizedVMOptions -XX:UseSVE=0"
volumes:
- ./docker/stack/ownership-real:/setup:ro
depends_on:
keycloak:
condition: service_healthy

ownership-seed:
image: postgres:16-alpine
entrypoint: ["psql", "-v", "ON_ERROR_STOP=1", "-f", "/setup/seed.sql"]
environment:
PGHOST: ownership-db
PGUSER: ownership
PGPASSWORD: ownership
PGDATABASE: ownershipdb
volumes:
- ./docker/stack/ownership-real:/setup:ro
depends_on:
ownership-real:
condition: service_healthy
keycloak-scopes:
condition: service_completed_successfully

alice-decks:
image: alteredcore-stack-web
entrypoint: ["php", "/var/www/html/docker/stack/ownership-real/seed-decks.php"]
volumes:
- .:/var/www/html
- ./docker/stack/ownership-real/config.php:/var/www/html/config.local.php:ro
depends_on:
web:
condition: service_healthy
5 changes: 3 additions & 2 deletions docker/stack/config.stack.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
define('DECKS_API_URL', 'http://decks-api:80');
define('CDN_URL', 'https://cdn.alteredcore.org');
// Mock of the digital-ownership service (docker/stack/ownership-mock): alt arts in the site and Re:Builder. It also
// answers the collection API's GET /api/collection (the real one only takes altered.re tokens).
define('OWNERSHIP_API_URL', 'http://ownership:8080');
// answers the collection API's GET /api/collection (the real one only takes altered.re tokens). The real service
// (docker-compose.ownership.yml) defines it first.
if (!defined('OWNERSHIP_API_URL')) define('OWNERSHIP_API_URL', 'http://ownership:8080');
define('OWNERSHIP_WEB_URL', '');
define('COLLECTION_API_URL', 'http://ownership:8080');
define('COLLECTION_USE_API', false);
Expand Down
39 changes: 27 additions & 12 deletions docker/stack/ownership-mock/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,39 +157,54 @@ function owned(array $print, string $user): ?int {
function options(array $f, string $user): array {
$chosen = state($user)['slots'][$f['key']] ?? [];
$slots = [];
for ($i = 0; $i < $f['copies']; $i++) $slots[] = ['slotIndex' => $i, 'reference' => $chosen[$i] ?? $f['prints'][0]['reference']];
// As the service: slots numbered from 1, the plain print where the player chose nothing.
for ($i = 0; $i < $f['copies']; $i++) {
$slots[] = ['slotIndex' => $i + 1, 'reference' => $chosen[$i] ?? $f['prints'][0]['reference'], 'isExplicitChoice' => isset($chosen[$i])];
}
return key3($f) + [
'options' => array_map(fn($p) => ['reference' => $p['reference'], 'ownedQuantity' => owned($p, $user)], $f['prints']),
'slots' => $slots,
];
}

/** Families of the chosen types (tokens by default), one page of the cards API per call. */
/**
* Families matching the filters, as the service: every card type by default (Common and Rare groups: Uniques have no
* alt art), `skip` / `take` counted in families. The cards API is read 200 groups at a time (about 30 of them have an
* alt art), only as far as the page asked for.
*/
function search(string $user): array {
$types = array_values(array_filter((array)($_GET['type'] ?? []), 'is_string')) ?: ['TOKEN', 'TOKEN_LANDMARK_PERMANENT', 'TOKEN_MANA'];
$types = array_values(array_filter((array)($_GET['type'] ?? []), 'is_string'));
$factions = array_values(array_filter((array)($_GET['faction'] ?? []), 'is_string'));
$rarities = array_values(array_filter((array)($_GET['rarity'] ?? []), 'is_string'));
// The collection API (cardType[], cardSet[]) fails on several card types, like the real one: its proxy filters them.
if (count((array)($_GET['cardType'] ?? [])) > 1) reply(['error' => 'several cardType'], 500);
$name = mb_strtolower(trim((string)($_GET['name'] ?? '')));
$locale = (string)($_GET['locale'] ?? 'fr');
$take = max(1, min(100, (int)($_GET['take'] ?? 25)));
$page = intdiv(max(0, (int)($_GET['skip'] ?? 0)), $take) + 1;
$q = 'itemsPerPage=' . $take . '&page=' . $page;
$skip = max(0, (int)($_GET['skip'] ?? 0));
$q = 'itemsPerPage=200&rarity[]=COMMON&rarity[]=RARE';
foreach ($types as $t) $q .= '&cardType[]=' . rawurlencode($t);
foreach ($factions as $fc) $q .= '&faction[]=' . rawurlencode($fc);
$res = cardsApi('/api/card_groups?' . $q);
$matched = [];
$more = true;
for ($page = 1; $more && count($matched) <= $skip + $take; $page++) {
$res = cardsApi('/api/card_groups?' . $q . '&page=' . $page);
foreach ($res['member'] ?? [] as $g) {
$f = toFamily($g);
if (!$f || ($rarities && !in_array($f['rarity'], $rarities, true))) continue;
$label = is_array($f['name']) ? ($f['name'][$locale] ?? $f['name']['en'] ?? reset($f['name'])) : $f['name'];
if ($name !== '' && !str_contains(mb_strtolower((string)$label), $name)) continue;
$matched[] = [$f, $label];
}
$more = $page * 200 < (int)($res['totalItems'] ?? 0);
}
$families = [];
$options = [];
foreach ($res['member'] ?? [] as $g) {
$f = toFamily($g);
if (!$f || ($rarities && !in_array($f['rarity'], $rarities, true))) continue;
$label = is_array($f['name']) ? ($f['name'][$locale] ?? $f['name']['en'] ?? reset($f['name'])) : $f['name'];
if ($name !== '' && !str_contains(mb_strtolower((string)$label), $name)) continue;
foreach (array_slice($matched, $skip, $take) as [$f, $label]) {
$families[] = key3($f) + ['cardType' => $f['cardType'], 'name' => $label, 'reference' => $f['prints'][0]['reference']];
$options[] = options($f, $user);
}
return ['families' => $families, 'options' => $options, 'hasMore' => $page * $take < (int)($res['totalItems'] ?? 0)];
return ['families' => $families, 'options' => $options, 'hasMore' => $more || count($matched) > $skip + $take];
}

/**
Expand Down
5 changes: 5 additions & 0 deletions docker/stack/ownership-real/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php
// Site configuration with the real AlteredOwnership service (docker-compose.ownership.yml): the stack's, with the
// digital-ownership service of the overlay instead of the mock.
define('OWNERSHIP_API_URL', 'http://ownership-real:8080');
require __DIR__ . '/docker/stack/config.stack.php';
Loading
Loading