"Override the name on the developer recipient slot. Leave blank to use whatever's set on the Documenso template.",
type:'string',
scope:'port',
},
{
key:'documenso_developer_email',
section:'documenso.signers',
label:'Developer signer — email',
description:
"Override the email on the developer recipient slot. Leave blank to use whatever's set on the Documenso template.",
type:'email',
scope:'port',
},
{
key:'documenso_developer_label',
section:'documenso.signers',
label:'Developer signer — label',
description:'Display label shown on the signing screen (defaults to "Developer").',
type:'string',
scope:'port',
placeholder:'Developer',
},
{
key:'documenso_developer_recipient_id',
section:'documenso.signers',
label:'Developer Documenso recipient ID',
description:
'Numeric Documenso recipient slot ID for the developer signer. Set automatically by "Sync from Documenso" — you rarely set this by hand.',
type:'number',
scope:'port',
envFallback:'DOCUMENSO_DEVELOPER_RECIPIENT_ID',
},
{
key:'documenso_developer_user_id',
section:'documenso.signers',
label:'Developer signer — linked CRM user (optional)',
description:
"Project Director RBAC binding. When set, the webhook handler fires an in-CRM notification for this user when it's their turn to sign — alongside the branded email. Leave blank if the developer slot doesn't map to a CRM user (e.g. external developer).",
type:'user-select',
scope:'port',
},
{
key:'documenso_approver_name',
section:'documenso.signers',
label:'Approver signer — name',
description:
"Override the name on the approver recipient slot. Leave blank to use whatever's set on the Documenso template.",
type:'string',
scope:'port',
},
{
key:'documenso_approver_email',
section:'documenso.signers',
label:'Approver signer — email',
description:
"Override the email on the approver recipient slot. Leave blank to use whatever's set on the Documenso template.",
type:'email',
scope:'port',
},
{
key:'documenso_approver_label',
section:'documenso.signers',
label:'Approver signer — label',
description:'Display label shown on the signing screen (defaults to "Approver").',
type:'string',
scope:'port',
placeholder:'Approver',
},
{
key:'documenso_approval_recipient_id',
section:'documenso.signers',
label:'Approver Documenso recipient ID',
description:
'Numeric Documenso recipient slot ID for the approver. Set automatically by "Sync from Documenso" — you rarely set this by hand.',
type:'number',
scope:'port',
envFallback:'DOCUMENSO_APPROVAL_RECIPIENT_ID',
},
{
key:'documenso_approver_user_id',
section:'documenso.signers',
label:'Approver — linked CRM user (optional)',
description:
"Same as developer's linked user — when set, fires an in-CRM notification when it's the approver's turn to sign.",
type:'user-select',
scope:'port',
},
{
key:'documenso_client_recipient_id',
section:'documenso.signers',
label:'Client recipient ID',
description:
'Documenso recipient ID for the client slot. Maps to DOCUMENSO_CLIENT_RECIPIENT_ID in env.',
'Auto = the system sends the branded "please sign" email immediately when an EOI/contract/reservation is generated. Manual = the document is generated and the signing URL appears in the UI; a rep clicks "Send invitation" to dispatch. Applies to all document types, not just EOI.',
type:'select',
options:[
{value:'manual',label:'Manual (rep clicks Send after generation)'},
{value:'auto',label:'Auto (send branded email on generate)'},
],
scope:'port',
defaultValue:'manual',
},
{
key:'documenso_reservation_template_id',
section:'documenso.templates',
label:'Reservation template ID',
description:'Template ID used for reservation agreements (optional).',
type:'number',
scope:'port',
},
{
key:'documenso_contract_template_id',
section:'documenso.templates',
label:'Contract template ID',
description:'Template ID used for the final purchase / lease contract (optional).',
// JSON map keyed by trigger name; value is one of 'auto' | 'suggest' |
// 'off'. Read by `getStageAdvanceMode` in port-config.ts. The registry
// entry uses the generic `string` type because the form generator's
// schemas don't have a JSON variant — the admin UI is a dedicated page
// (/admin/pipeline-rules) that renders 3-way toggles per trigger.
{
key:'stage_advance_rules',
section:'pipeline.auto_advance',
label:'Pipeline auto-advance rules',
description:
'Per-trigger control for whether lifecycle events (EOI sent/signed, deposit received, etc.) auto-advance the deal stage, only suggest the move via a notification, or do nothing.',
// ─── AI / OpenAI ──────────────────────────────────────────────────────────
{
key:'ai_enabled',
section:'ai.master',
label:'AI features enabled',
description:
'Master switch. When OFF, every AI surface (receipt OCR, berth-PDF AI parse) is bypassed. Provider keys stay configured but unused.',
type:'boolean',
scope:'port',
defaultValue: true,
},
{
key:'ai_monthly_token_cap',
section:'ai.master',
label:'Monthly token cap (this port)',
description:
'Soft cap on total AI tokens consumed per calendar month. When exceeded, AI features fall back to non-AI paths and surface a banner. Set 0 for no cap.',
type:'number',
scope:'port',
defaultValue: 0,
},
{
key:'openai_api_key',
section:'ai.providers',
label:'OpenAI API key',
description:'Used by Receipt OCR fallback and berth-PDF AI parse. AES-encrypted at rest.',
type:'password',
scope:'port',
encrypted: true,
sensitive: true,
envFallback:'OPENAI_API_KEY',
placeholder:'sk-…',
},
{
key:'openai_default_model',
section:'ai.providers',
label:'Default OpenAI model',
description:'Used when a feature does not specify an explicit model.',
"When set, the supplemental-info email links to this URL with ?token=… appended (typically the marketing site's hosted form). Leave blank to use the built-in CRM form at /public/supplemental-info/<token>. Useful when you want the client to land on a branded marketing-site page instead of the CRM domain.",
// Per-port admin controls for the deal-pulse chip on interest lists +
// detail headers. Master toggle hides the chip entirely; per-signal
// toggles let admins quiet specific signal types; label overrides
// rename tier labels for ports that prefer their own vocabulary.
{
key:'pulse_enabled',
section:'pulse',
label:'Show deal pulse chips',
description:
'Master toggle. When off, the pulse chip is hidden on every interest list row + detail header for this port. Useful when a port prefers to triage pipelines without the AI-tinted chip.',
type:'boolean',
scope:'port',
},
{
key:'pulse_signal_eoi_sent_recent_enabled',
section:'pulse',
label:'Signal: recent EOI sent (positive)',
description:'Default on. Brightens chip when EOI was sent in last 14 days.',
type:'boolean',
scope:'port',
},
{
key:'pulse_signal_deposit_received_enabled',
section:'pulse',
label:'Signal: deposit received (positive)',
description:'Default on. Strong forward signal once a deposit invoice flips to paid.',
type:'boolean',
scope:'port',
},
{
key:'pulse_signal_contract_signed_enabled',
section:'pulse',
label:'Signal: contract signed (positive)',
description:'Default on. Reinforces closed-loop progress until outcome flips to won.',
type:'boolean',
scope:'port',
},
{
key:'pulse_signal_document_declined_enabled',
section:'pulse',
label:'Signal: document declined (risk)',
description:
'Default on. Strongest cooling signal — client refused to sign an EOI / contract / reservation. Requires the risk-data wiring shipped alongside Phase 2 to populate.',
type:'boolean',
scope:'port',
},
{
key:'pulse_signal_reservation_cancelled_enabled',
section:'pulse',
label:'Signal: reservation cancelled (risk)',
description:'Default on. Booked-then-cancelled signals require rep attention.',
type:'boolean',
scope:'port',
},
{
key:'pulse_signal_berth_sold_to_other_enabled',
section:'pulse',
label:'Signal: berth resold (risk)',
description:'Default on. Primary berth got linked to a different completed interest.',
type:'boolean',
scope:'port',
},
{
key:'pulse_label_hot',
section:'pulse',
label:'Custom label: Hot tier',
description:'Leave blank to use the built-in "Hot" label.',
type:'string',
scope:'port',
placeholder:'Hot',
},
{
key:'pulse_label_warm',
section:'pulse',
label:'Custom label: Warm tier',
description:'Leave blank to use the built-in "Warm" label.',
type:'string',
scope:'port',
placeholder:'Warm',
},
{
key:'pulse_label_cold',
section:'pulse',
label:'Custom label: Cold tier',
description:'Leave blank to use the built-in "Cold" label.',
'Comma-separated list of email addresses that receive a copy of every new residential inquiry the moment it lands. Leave blank to disable partner forwarding. Reps still see every inquiry in the CRM; this is an outbound courtesy notification for an external partner who handles residential leads on the port’s behalf.',