Skip to content

[OpenSpec] portal-contribution #452

Description

@github-actions

⚠️ OpenSpec-managed issue — this content is automatically synced
from the openspec/ directory. Manual edits will be overwritten on next sync.

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\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.

Specs

Tasks

  • 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.

Design

See design.md for technical design details.


Synced from openspec/changes/portal-contribution by OpenSpec workflow
App: larpinq

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions