feat(shard): follow the visibility framework and read the Protocol 3.0 profile
All checks were successful
PR Checks / android-build (pull_request) Successful in 6m20s
All checks were successful
PR Checks / android-build (pull_request) Successful in 6m20s
M11 Part 1 (docs/android/PLAN.md §9). The website's Protocol 3.0 work made every
shard-derived surface admin-configurable — a feature can be switched off, or its
audience raised above the caller's rung — and the app knew nothing about it: it
gated shard navigation on the session role alone, so an admin change left the
drawer and the hub offering entries that 404/403 into a generic error where the
web client hides them.
The visibility rules:
- GET /public/shard/features behind a singleton ShardFeaturesRepository,
re-resolved on every session change (the answer is per-viewer) and dropped on
a Settings → Server switch, which is the one case no session change covers.
- MenuEntry gains `feature` beside `access`; the two gates are independent and
both must pass. ShardBoard tags each hub tile the same way.
- An unknown answer FAILS OPEN, matching lib/useShardFeatures.js: the server
gates every call regardless, so a link that briefly 403s beats a drawer that
flickers its entries in on every cold start. A pre-3.0 website 404s this
route, which reads as "unknown" and behaves exactly as before.
- toShardUiState() maps 404 AND 403 to a new ErrorKind.FEATURE_UNAVAILABLE:
requireFeature answers 404 for a disabled feature (deliberately not
disclosing it exists) and 403 for a viewer below its rung. Kept separate from
toUiState() because both statuses mean something else off the shard surface —
a deleted post, an ownership refusal. That state renders without a retry
button; an admin controls it, so retrying cannot change the answer.
The read-model adds, from the same v3 series:
- char.profile `points` — the Loyalty & Points block. maxPoints 0 means
UNCAPPED and is the common case, so nothing divides by it and only a capped
system gets a meter; nameString is usually null (systems name themselves with
a cliloc) so humanising the PointsType key is the primary display path; rank
is absent unless the shard opts in, and absent is not "unranked".
- Cliloc-resolved names — equipment `clilocName` and titles `rewardResolved`,
so items stop rendering as a layer. rewardResolved is positional: an entry
the table could not resolve is null and is skipped WITHOUT shifting the
`selected` index onto its neighbour.
ActorDto keeps acct/webId but documents them as admin-locked rather than
available. Points ride ungated on /player/shard/char/:serial — a character's own
standings are self-service and do not depend on the public leaderboards feature,
so the app mirrors that rather than re-gating it.
304 unit tests pass; lint clean.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
<string name="error_not_found">This content couldn\'t be found.</string>
|
||||
<string name="error_rate_limited">Too many requests. Please try again in a moment.</string>
|
||||
<string name="error_shard_offline">The shard is offline right now.</string>
|
||||
<string name="error_feature_unavailable">This shard doesn\'t publish this here.</string>
|
||||
<string name="error_server">Something went wrong on the server. Please try again.</string>
|
||||
|
||||
<!-- ── First-run connect (§3) ──────────────────────────────────────── -->
|
||||
@@ -290,6 +291,11 @@
|
||||
<string name="player_char_pois">Poison</string>
|
||||
<string name="player_char_energy">Energy</string>
|
||||
<string name="player_char_skills">Skills</string>
|
||||
<string name="player_char_points">Loyalty & Points</string>
|
||||
<!-- A point system's name followed by the character's rank on that board, e.g. "Queens Loyalty · #3". -->
|
||||
<string name="player_char_points_ranked">%1$s · #%2$d</string>
|
||||
<!-- A score against its cap. Only shown for capped systems; an uncapped score shows the number alone. -->
|
||||
<string name="player_char_points_of">%1$d / %2$d</string>
|
||||
<string name="player_char_equipment">Equipment</string>
|
||||
<string name="player_char_item">Item</string>
|
||||
<string name="player_char_item_id">id %1$d</string>
|
||||
|
||||
Reference in New Issue
Block a user