You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Contribute Larpinq's player-facing surfaces to the shared portaliq
external portal (hydra ADR-046 + contract v2.1) instead of building a bespoke
portal. Larpinq ships ONE plain, dependency-free class OCA\Larpinq\Portal\PortalContributionProvider that declares — for the
single player audience — the OpenRegister collections a portal subject may
read and the whitelisted create-action they may perform. Portaliq discovers the
class by convention FQCN, duck-types it (never instanceof), and serves the
collections scoped to the subject. Without portaliq installed the class is
inert and Larpinq behaves exactly as before.
T1: Verify the full scoping map against the register JSONs at HEAD (larpinq_register.json + register.d/*.json) — schemas, the ownerRef scoping property (uuid, from portal-identity), and the game-master-only columns to exclude.
T2: Add lib/Portal/PortalContributionProvider.php — plain, dependency-free (no portaliq import, no implements, no constructor deps), EUPL-1.2/SPDX docblock matching the repo, @spec tags.
T3: Implement getAudiences(): array returning ['player'] and the v1 fallback getAudience(): string returning 'player'.
T4: Implement getContribution(array $subject): ?array — branch on $subject['audience'] only; return null for anything else (fail-closed, no endpoint actions).
T5: Player read collections: myCharacters (scopeField: ownerRef, scopeClaim: ownerRef, field-projected) + public events, skillCatalog, itemCatalog, conditionCatalog (each scopeField: ''), catalogs projected to reference columns.
T6: Player action: createCharacter (type: create, scopeField: ownerRef so the writer stamps the owner) with fields name, ocName, background only; notifications: []; no inbox collection.
T7: Add tests/unit/Portal/PortalContributionProviderTest.php — direct construction, nil-UUID subject (design.md Seed Data), pinning the dependency-free shape, audiences, collection shape, field whitelists, create whitelist, fail-closed null, and a register-drift pin (scoping key + whitelist columns exist on their schema at HEAD).
T8: Create openspec/changes/portal-contribution/specs/portal-contribution/spec.md (status: in-progress) and run openspec validate portal-contribution --strict until valid.
T9: Run the gate suite the CI way (docker php:8.3-cli): composer lint, composer phpcs, composer phpmd, composer phpstan, and the unit suite (vendor/bin/phpunit -c phpunit-unit.xml); fix violations in the files this change touches (max 3 cycles, report honestly). Psalm is CI-disabled for this repo.
T10: Commit on feat/portal-contribution (conventional message, no Co-Authored-By); do not push, do not open a PR.
Artifacts
Summary
Contribute Larpinq's player-facing surfaces to the shared portaliq
external portal (hydra ADR-046 + contract v2.1) instead of building a bespoke
portal. Larpinq ships ONE plain, dependency-free class
OCA\Larpinq\Portal\PortalContributionProviderthat declares — for thesingle
playeraudience — the OpenRegister collections a portal subject mayread and the whitelisted create-action they may perform. Portaliq discovers the
class by convention FQCN, duck-types it (never
instanceof), and serves thecollections scoped to the subject. Without portaliq installed the class is
inert and Larpinq behaves exactly as before.
Specs
Tasks
larpinq_register.json+register.d/*.json) — schemas, theownerRefscoping property (uuid, from portal-identity), and the game-master-only columns to exclude.lib/Portal/PortalContributionProvider.php— plain, dependency-free (no portaliq import, no implements, no constructor deps), EUPL-1.2/SPDX docblock matching the repo,@spectags.getAudiences(): arrayreturning['player']and the v1 fallbackgetAudience(): stringreturning'player'.getContribution(array $subject): ?array— branch on$subject['audience']only; returnnullfor anything else (fail-closed, no endpoint actions).myCharacters(scopeField: ownerRef,scopeClaim: ownerRef, field-projected) + publicevents,skillCatalog,itemCatalog,conditionCatalog(eachscopeField: ''), catalogs projected to reference columns.createCharacter(type: create,scopeField: ownerRefso the writer stamps the owner) with fieldsname,ocName,backgroundonly;notifications: []; noinboxcollection.tests/unit/Portal/PortalContributionProviderTest.php— direct construction, nil-UUID subject (design.md Seed Data), pinning the dependency-free shape, audiences, collection shape, field whitelists, create whitelist, fail-closed null, and a register-drift pin (scoping key + whitelist columns exist on their schema at HEAD).openspec/changes/portal-contribution/specs/portal-contribution/spec.md(status: in-progress) and runopenspec validate portal-contribution --strictuntil valid.composer lint,composer phpcs,composer phpmd,composer phpstan, and the unit suite (vendor/bin/phpunit -c phpunit-unit.xml); fix violations in the files this change touches (max 3 cycles, report honestly). Psalm is CI-disabled for this repo.feat/portal-contribution(conventional message, no Co-Authored-By); do not push, do not open a PR.Design
See design.md for technical design details.
Synced from
openspec/changes/portal-contributionby OpenSpec workflowApp:
larpinq