Ports and forms
The three rules about what is bound and what the forms declare — the seven required ports, the install form, the settings form.
ports.required_bound
Checks that the connector binds all seven ports every connector must bind, whatever its capabilities: InstallationLifecycle, IdentityResolver, InboundGateway, FailureClassifier, TextRenderer, SettingsSchema, UiSlots.
Fails with ports every connector must bind: Subscriby\Connector\Contracts\Ports\TextRenderer, Subscriby\Connector\Contracts\Ports\UiSlots.
Why the core calls these for every connector: to connect it, to know who an event is from, to accept the platform's calls, to read a refusal, to render a message, to draw the install form, to render (or not render) its UI.
Fix bind each in Connector::register(). SettingsSchema is bound for you when the manifest declares fields; UiSlots must be bound even to return an empty list.
The agreement between capabilities and capability-bound ports is checked by the registry when the connector registers, not here: a declared capability without its port, or a bound port without its capability, refuses the package with InvalidManifest before the kit can run, in the application at boot and in your own suite at TestRegistry::register() (capabilities).
settings.install_fields
Checks SettingsSchema::installFields(): every entry is a Field, no name is declared twice, every field has a non-empty label; and, for a paste_credential connector, at least one field is an input (text, secret, select, toggle) and at least one is a secret.
Fails with install fields: "token" is declared twice, "intro" has no label, a paste-a-credential connector declares no secret field.
Why the dashboard, the API and the apps render the form from these fields; a duplicate name loses a value, a missing label shows an empty input, and a paste-a-token connector without a secret has nothing to paste.
Fix the fields in connector.json (or your own schema). A field's own rules (identifier name, options on a select, https or mailto links) are enforced by the Field constructor and reported by the loader.
settings.settings_fields
Checks SettingsSchema::settingsFields(null) the same way: Field entries, unique names, labels. The paste_credential clause does not apply.
Fails with settings fields: "welcome" has no label.
Why the Configuration tab renders these after install, with the current values filled in.
Fix as above. A connector with nothing to configure returns an empty list, which passes.
Called with null
The kit asks for the settings fields with no installation, so an own SettingsSchema must answer the defaults when given null rather than assume an installation is in hand. The catalogue does the same when it publishes the fields over GET /connectors.
How is this guide?
Manifest rules
The five rules about connector.json — the key, the SDK constraint, the listing links, the resource kinds, and that the registered manifest is what the file on disk says.
Rendering and failures
The three rules that exercise the TextRenderer and the FailureClassifier with real inputs — plain text, the canonical sample, an arbitrary throwable and an arbitrary value.