Resources
The resource rows as a connector may read them, and the one write — selling access to a place a creator picked — with its idempotency, its authorisation, its refusals and what the core announces.
Subscriby\Connector\Core\Resources. A space is a place the installation administers; a resource is the core's decision to sell access to it. Recording a place through Spaces::record() sells nothing. This contract is where the decision is written: the moment the platform answers a SpaceCatalog link request with the place the creator chose, the connector records the place and asks for the resource here, and the core writes the row, binds it to the space and announces it exactly as the dashboard would have.
Reads
| Method | Returns | Null when |
|---|---|---|
find(string $id) | ?ResourceRef | No resource has that UUID. |
findBySpace(SpaceRef $space) | ?ResourceRef | No project sells that place. |
listForProject(ProjectRef $project, string $connector) | list<ResourceRef> | Never null; the project's resources on your connector, oldest first. |
findBySpace() answers by the space row or, for a connector whose pre-SDK rows the core still mirrors, by the row the place's storageRef names, so a place reads the same before and after the core has bound its resource.
create()
$resource = $resources->create(
new ProjectRef($parked->project_id),
$space, // recorded through Core\Spaces first
ResourceKind::for('example', 'room'),
title: $room->title,
description: __('Access to :room while your membership is active.', ['room' => $room->title]),
);The core writes the row under the project, active, with the kind's connector, kind and space written together (the same step as Spaces::bindResource()), broadcasts it to the creator's open dashboard, and emits project.resource.linked with connector, kind and space_id beside the fields the event always carried.
Idempotent on the project and the place. A place the project already sells is answered with its resource rather than a second row, so a connector may call this on every answer the platform gives, including a replayed one.
Authorised as the dashboard is. The write acts for the creator the request runs as: the inbound handler that received the platform's answer, or the web request the creator made on your picker page. It is refused exactly as "Add a resource" would be for someone who may not add resources to that project, and a call with nobody acting is refused too.
Refusals
Subscriby\Connector\Exceptions\ResourceRefused, with a stable reason a connector can branch on and a message for the developer, never for a creator:
reason | When |
|---|---|
kind_outside_place | The kind is manual or names another connector than the place's. |
place_unknown | The space was never recorded through Core\Spaces. |
project_unknown | No project has that id. |
not_permitted | The actor may not add resources to the project, or nobody is acting. |
resource_unknown | Raised by the recovery writes that name a resource. |
What the ref carries
ResourceRef: id, projectId, kind (a ResourceKind, connector:kind; the manual perk while the core has bound the resource to no place), title, spaceId, active. Plans, grants and health never travel on it: the core decides who may be in a place and asks your ports to act.
Finish the request, then forget it
Record the place, create the resource, then delete whatever you parked for the request. The core's Resources page shows the new row at once, and the creator adds it to a plan from there; a connector never touches plans.
How is this guide?
Spaces
The space rows as a connector may read and write them — finding a place, recording every place the installation learns about, and pointing a resource at one.
Grants
The access ledger as a connector may read and write it — finding a grant by id or by the reference you issued, what a summary tells you, and when a connector records a grant itself.