Metadata-Version: 2.4
Name: ocyan.plugin.hubspot
Version: 0.1.1rc1
Summary: Guarded MandelBlog HubSpot enquiry intake boundary
Author-email: MandelBlog <info@mandelblog.com>
License-Expression: LicenseRef-Proprietary
Project-URL: Repository, https://git.mandelblog.com/mandel-plugins/ocyan.plugin.hubspot
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Requires-Python: <3.13,>=3.12
Description-Content-Type: text/markdown

# ocyan.plugin.hubspot

MandelBlog's guarded HubSpot CRM integration boundary.

This initial implementation contains a read-only legacy form-submission adapter and a guarded Enquiry intake service. It does not schedule itself and does not execute HubSpot mutations unless a caller explicitly invokes the canary/write path.

## Scope

- Native HubSpot Enquiry form submissions.
- Current date-based Contact and Task APIs (`2026-03`), verified against the
  current HubSpot developer reference.
- Guarded lifecycle, lead-status, owner, and follow-up-task policy.
- Durable SQLite cursor/idempotency/dead-letter state.
- No Deals, Companies, native Leads, workflows, consent changes, marketing automation, or custom properties.

The form-submission endpoint is intentionally isolated in `FormSubmissionAdapter`
because HubSpot currently exposes that read surface through the legacy Forms API.
It is a compatibility adapter, not a reason to use legacy CRM object paths.

## Configuration

Configuration is supplied by the host application or an approved secret-management mechanism. The package never reads or stores credentials in source control.

Required values:

- HubSpot account ID.
- HubSpot Service Key reference, resolved at runtime as `HUBSPOT_ACCESS_TOKEN`.
- Approved Enquiry form ID.
- Confirmed MandelBlog owner ID.
- SQLite state path outside the repository.

The canary requires an explicit form ID and submission `conversionId`; it must not process arbitrary historical submissions.

## Development

```bash
python3.12 -m unittest discover -s tests -v
python3.12 -m json.tool config.example.json >/dev/null
```

Production scheduling, deployment, and the real canary require separate approval.

## API and safety contract

`HubSpotClient` targets the currently documented date-versioned CRM object paths:

- Contacts: `/crm/objects/2026-03/contacts`
- Tasks: `/crm/objects/2026-03/tasks`

It deliberately has no ambient write behaviour. A consumer must explicitly enable
the approved canary path before the guarded intake service can update a Contact or
create its one associated Task. Runtime credentials remain in the host's approved
secret mechanism; API error text is redacted before it reaches callers.

Certification uses deterministic fake transports only. A live API smoke test is
separately approved, opt-in operational work and is not needed to install, test,
or certify this package.
