Security Overview
Product: Keelstone Actions
Publisher: Keelstone
Contact: security@keelstone.dev
Document version: 1.3
Last updated: April 2026
Executive Summary
Keelstone Actions is a Salesforce managed package that enables Salesforce Screen Flows to read and write Microsoft Office documents (Excel, Word, PowerPoint) and Google Workspace documents (Sheets, Docs, Slides) through a cloud relay architecture. This document describes the security design, data handling practices, authentication model, and compliance posture of the Keelstone platform for the benefit of Salesforce security reviewers, enterprise security teams, and IT administrators evaluating the product.
Key security properties:
- No Salesforce data is stored by Keelstone. The relay service acts as a stateless command broker. Salesforce data passes through in transit only and is never persisted outside Salesforce.
- All traffic is encrypted. Every connection between components uses TLS 1.2 or higher. No plaintext endpoints exist.
- Salesforce credentials are never sent to Keelstone servers. Authentication uses Salesforce-issued OAuth 2.0 access tokens obtained via PKCE. Keelstone never sees or stores usernames or passwords.
- All Apex code runs with sharing enforced. Every Apex class uses
with sharingand checks field-level security before data access. - The relay session is short-lived and scoped. Each Keelstone session ID is a random UUID tied to a single user and invalidated on logout.
Architecture Overview
Keelstone has three components:
Salesforce Org
Contains the managed package (kstone namespace). Apex invocable actions run inside the customer's org, under the customer's Salesforce security model (profiles, permission sets, field-level security, sharing rules). No data leaves Salesforce except the specific values passed by the admin-controlled Flow.
Keelstone Cloud (app.keelstone.dev)
A cloud-hosted relay service. Its sole function is to forward commands from Salesforce to the correct Office or Google Workspace session and return the result. It does not store document data, Salesforce record data, or field values. Document content never passes through the relay — only control commands (e.g., "write these values to range A1:C10") and their results. The only data persisted is:
- Session records (UUID, org ID, user ID, creation/expiry timestamps, active flag)
- Org registration records (Salesforce org ID, instance URL, plan tier, created timestamp)
- Merge count records (org ID, user ID, doc type, timestamp) — used for plan limit enforcement
Office Taskpane / Google Workspace Add-on
An Office JS add-in running inside Excel, Word, or PowerPoint (or a Google Apps Script add-on for Sheets, Docs, and Slides). It maintains a persistent connection to the relay service. When it receives a command, it executes the corresponding document API call and returns the result. All document access is local — no document content is sent to the relay service.
The taskpane also monitors the open document for selection changes, cell edits, sheet activations, and slide changes. These events are forwarded to any open flow dialog, allowing LWC components inside flows to react to live document state. Only event metadata (e.g., selected range address, selected text) is forwarded — no document bytes are transmitted.
Authentication and Authorization
Salesforce OAuth 2.0 with PKCE
Keelstone uses OAuth 2.0 Authorization Code flow with PKCE (Proof Key for Code Exchange) and a Salesforce External Client App (ECA). The ECA is created automatically by the post-install Apex job and is scoped to the minimum permissions required. No client secret is used — PKCE replaces it, eliminating the risk of secret exposure.
OAuth scopes requested: api web refresh_token
api— required to call Salesforce REST APIs for data queries and file operationsweb— required for Lightning Out session compatibilityrefresh_token— allows silent session renewal without re-prompting the user
What Keelstone receives from OAuth:
- An
access_token(Salesforce-issued, short-lived) - A
refresh_token(Salesforce-issued, used only to refresh the access token) - The user's Salesforce user ID and org ID (from the identity endpoint)
Keelstone does not receive or store:
- The user's Salesforce username or password
- The user's email address or personal information
- Any Salesforce record data during the OAuth exchange
The access_token is stored server-side in the session record and used to make API calls on behalf of the user when server-side document generation is requested (e.g., downloading a template file from Salesforce Files). It is never returned to the browser or to the Salesforce Flow.
Keelstone Session ID
When a user authenticates, the relay service creates a Keelstone session: a random UUID (cryptographically generated) stored with a reference to the Salesforce user ID and org ID.
This session ID is:
- Passed to the Office or Google taskpane and stored in
localStorageatapp.keelstone.dev - Injected into the Salesforce Screen Flow as the
KeelstoneSessionIdinput variable by the taskpane at launch time - Used by Apex actions as a Bearer token on all requests to the relay service
- Never transmitted to Salesforce — it flows from the taskpane into the flow dialog via the flow launch parameters only
The session ID is treated as a secret. Any request to the relay API that presents a valid session ID is authorized to issue commands to the taskpane session associated with it. Sessions are invalidated on explicit logout and expire after 24 hours of inactivity.
Relay Service Authorization
Every relay API endpoint requires a valid Authorization: Bearer <sessionId> header. The relay service validates the session ID before processing any request. Invalid or expired sessions receive HTTP 401.
The relay service additionally enforces:
- Plan tier checks: Free-tier orgs are limited to 1 visible action in the taskpane
- Merge limits: Document generation is rate-limited per plan tier:
- Free: 5 merges per org per month
- Pro: 100 merges per user per month
No Privilege Escalation
Keelstone Actions operate entirely within the Salesforce user's existing permissions. The Apex invocable actions run as the calling user (with sharing). If the calling user does not have read access to a field or object, the Apex query will not return that data — Keelstone has no mechanism to bypass Salesforce field-level security or sharing rules.
Data Handling
What data passes through the relay service
The relay service forwards command payloads between the Apex action and the taskpane. Payloads may contain:
- Data values that the Flow developer explicitly chose to write to the document (e.g., opportunity names, amounts, dates)
- Cell addresses and range references
- Chart configuration parameters
- HTML or text content for Word insertion
- Document property keys and values
- Office event metadata (e.g., selected range address, selected text snippet, active worksheet ID) — forwarded to flow dialogs on the same session
The relay service does not inspect or log payload contents. Payloads are forwarded opaquely. Logs capture event types and session IDs for debugging but not payload values.
Server-side document generation
For template merge operations, the relay service temporarily holds document bytes in memory during processing:
- Resolves
templateKey→ queries the most recent ContentDocumentLink on theKeelstone_Template__crecord - Downloads the template from Salesforce Files using the user's access token
- Merges the provided data into the template in-memory
- Uploads the result to Salesforce Files using the user's access token
- Returns only the resulting
ContentDocumentId— the bytes are discarded immediately
No document content is written to disk or stored in the database at any point during this process.
Document identity properties
When a generated document is inserted into the open Word or Excel document, Keelstone writes two custom properties directly into the Office file:
| Property | Value | Purpose |
|---|---|---|
_ks_doc_id | ContentDocumentId of the generated file | Document provenance tracking |
_ks_template_key | Template Key slug (e.g. "welcome-packet") | Template-scoped action filtering |
These properties are stored entirely within the Office document file (.docx / .xlsx) on the user's local machine or OneDrive — they are not sent to the Keelstone relay service. On next taskpane open, the taskpane reads _ks_template_key and sends it to the config endpoint as a URL query parameter to filter the action list. Only the key string (a short developer-chosen slug) is transmitted — no document content.
Invocable actions KS_GetDocumentProperty and KS_SetDocumentProperty explicitly block access to _ks_doc_id and _ks_template_key to prevent flows from reading or overwriting these internal markers.
What data is NOT sent to Keelstone
- Salesforce record data not referenced by the Flow — Flows only pass the data they explicitly wire to action inputs
- Document content from Office or Google Workspace — Document content is never uploaded to the relay service as part of taskpane relay operations. The
KS_GetRangeaction returns cell values to the Flow, but this data stays within the Salesforce → relay → Salesforce round trip and is not stored. - User credentials — Usernames, passwords, and MFA tokens are never transmitted to Keelstone
- Personal data — Keelstone does not collect names, email addresses, or any PII beyond the Salesforce user ID (a system identifier, not PII under most definitions)
Data retention
| Data | Retention |
|---|---|
| Session records | Deleted on logout; automatically expired after 24 hours of inactivity |
| Org registration records | Retained while the org is active; deleted on request |
| Merge count records | Retained for 13 months for plan limit calculation and billing |
| Application logs | Retained for 30 days; contain session IDs and event types but not payload data |
| Salesforce OAuth tokens | Access token: stored encrypted, in use for session lifetime; refresh token: stored encrypted, deleted on logout |
Data residency
The relay service is hosted in the United States. Customers with data residency requirements outside the US should contact support@keelstone.dev before deploying.
Network Security
Transport encryption
All connections use TLS 1.2 or higher:
| Connection | Protocol |
|---|---|
| Browser → app.keelstone.dev | HTTPS / WSS (TLS 1.2+) |
| Apex → app.keelstone.dev | HTTPS |
| Relay service → session store | TLS |
HTTP requests to app.keelstone.dev are redirected to HTTPS (301). No plaintext connections are accepted.
Endpoint security
All Keelstone invocable actions call endpoints under https://app.keelstone.dev/api/. All endpoints require a valid Bearer session token. Unauthenticated requests return HTTP 401.
Infrastructure
The relay service has no inbound ports open other than 443 (HTTPS). The session store is not publicly accessible. DDoS protection is provided at the infrastructure edge.
Salesforce Package Security
Apex security practices
All Apex classes in the Keelstone Actions package follow Salesforce security best practices:
| Practice | Implementation |
|---|---|
with sharing | Every Apex class declares global with sharing |
| FLS checks | isAccessible() checked before any SOQL query on ContentVersion and other objects |
| CRUD checks | Object-level access validated before DML operations |
| No dynamic SOQL | All SOQL queries use static, parameterized form |
| Input validation | Session ID is validated server-side; no user-supplied input is concatenated into SOQL |
| No stored credentials | No Salesforce credentials, API keys, or secrets are stored in Apex code or custom settings visible to users |
Callout security
Every Apex invocable action makes a single HTTPS callout to https://app.keelstone.dev. The callout:
- Uses
Authorization: Bearer <sessionId>for authentication - Sets a 30-second timeout
- Does not follow redirects
- Requires the remote site
https://app.keelstone.devto be in the org's Remote Site Settings (installed automatically by the package)
The session ID used as the Bearer token is the Keelstone session UUID — it does not contain any Salesforce credentials or tokens.
Package permissions
The Keelstone Actions package requests the following permissions:
| Permission | Reason |
|---|---|
Read/Write Keelstone_Action__c | Admin configuration of action tiles |
Read/Write Keelstone_Group__c | Admin configuration of action groups |
Read/Write Keelstone_Template__c | Admin configuration of template registry records |
Read/Write Keelstone_Template_Action__c | Admin configuration of template-scoped action visibility |
Read/Write Keelstone_Setting__mdt | Post-install registration and org branding configuration |
| Create External Client Apps (post-install only) | One-time ECA creation via post-install Apex |
Callout to https://app.keelstone.dev | All invocable action calls and document generation |
No permissions to standard Salesforce objects (Accounts, Contacts, Opportunities, etc.) are requested by the package itself. Data access to those objects is determined entirely by the Flow the admin builds and the permissions of the running user.
Lightning Locker / LWC Security
The keelstoneGenerateDocument LWC component runs inside Salesforce's Lightning Locker Service. It:
- Does not access the DOM of other components
- Does not make cross-origin requests from the LWC layer (all HTTP calls go through Apex)
- Fires standard
FlowAttributeChangeEventandFlowNavigationFinishEventonly - Does not use
eval()or dynamic code execution
Third-Party Services
| Service | Purpose | Data shared |
|---|---|---|
| Microsoft Office JS | Document API in Excel, Word, PowerPoint | No data sent to Microsoft beyond normal Office telemetry. Keelstone's Office JS code is local. |
| Google Apps Script | Google Workspace add-on runtime | No data sent to Google beyond normal Apps Script telemetry. Keelstone's Apps Script code runs in the customer's Google account. |
Keelstone does not use advertising networks, analytics platforms, or any third-party service that receives Salesforce record data.
Vulnerability Management
Responsible disclosure
Security vulnerabilities should be reported to security@keelstone.dev. We commit to:
- Acknowledging reports within 2 business days
- Providing a remediation timeline within 10 business days
- Notifying affected customers if a vulnerability affected production data
Dependency management
Server-side dependencies are audited on every deployment. Critical and high-severity findings are remediated before deployment. The Salesforce package has no third-party Apex dependencies.
Penetration testing
Keelstone has not yet conducted formal third-party penetration testing. We intend to commission an external assessment prior to general availability on AppExchange. Key design mitigations:
- Authentication bypass: All relay endpoints require a valid Bearer session ID. Session IDs are cryptographically random 128-bit UUIDs and are not guessable or enumerable.
- IDOR: Session IDs are the only key used to scope requests. There are no sequential numeric identifiers exposed in any API.
- Injection: All database queries use parameterized statements. No user-supplied input is concatenated into queries.
- XSS: The relay service returns JSON only. No HTML is rendered server-side from user input.
Customers and AppExchange security reviewers may request our internal security review notes by contacting security@keelstone.dev.
Compliance and Certifications
| Framework | Status |
|---|---|
| Salesforce AppExchange Security Review | In progress |
| OWASP Top 10 (2021) | Self-assessed — design controls in place; formal third-party pen test planned pre-GA |
| SOC 2 Type II | Not currently certified. Infrastructure provider maintains SOC 2 Type II certification. |
| GDPR | Keelstone processes no personal data beyond Salesforce user IDs. No special category data is processed. Contact security@keelstone.dev for a Data Processing Agreement if required. |
| HIPAA | Not certified. Customers subject to HIPAA must not use Keelstone to process PHI without a signed BAA. Contact security@keelstone.dev. |
Incident Response
In the event of a confirmed security incident affecting customer data:
- The relay service is taken offline within 1 hour of confirmation to contain the incident
- All active sessions are invalidated
- Affected customers are notified within 24 hours with a description of the impact and remediation steps
- A post-incident report is published within 14 days
Customers who believe their Keelstone account has been compromised should contact security@keelstone.dev immediately and revoke the Keelstone ECA in their Salesforce org (Setup → External Client Apps → Keelstone → Revoke).
Security Checklist for Administrators
Before deploying Keelstone in a production org, administrators should:
- Confirm the
Keelstone_Userpermission set is assigned only to users who need access - Review the Keelstone Action records to ensure only approved flows are exposed as action tiles
- Confirm that the flows referenced by Action records follow your org's data access policies
- Review which Salesforce fields are wired into Keelstone action inputs — only pass the minimum data needed
- Confirm Remote Site Settings includes
https://app.keelstone.devand no other Keelstone-related entries exist - If using document generation with public links (
externalLink = true), confirm your data classification policy permits public distribution of the generated content - If using org branding, confirm the logo uploaded via the Setup page does not contain sensitive information (it is stored as a publicly accessible Salesforce ContentDistribution URL)
Contact
Security issues: security@keelstone.dev
Privacy questions: privacy@keelstone.dev
General support: support@keelstone.dev
Documentation: https://docs.keelstone.dev