Commit Graph

2 Commits

Author SHA1 Message Date
Abdul Rahman 4c4a154d31 key-value storage for applications (#23089)
## What

Key-value storage for applications, as proposed in
twentyhq/core-team-issues#2391 — built on the existing `keyValuePair`
entity:

- Nullable `applicationId` relation on `keyValuePair` + a new
`APPLICATION_VARIABLE` type (fast instance command included)
- GraphQL CRUD on the metadata schema (`appKeyValue`, `setAppKeyValue`,
`deleteAppKeyValue`), requiring an `APPLICATION_ACCESS` token —
`applicationId` always comes from the token, never from arguments, so
apps can't touch each other's entries
- `kv.get` / `kv.set` / `kv.delete` helpers in
`twenty-sdk/logic-function`

## Scopes

- **`INSTALL`** (default): entries are private to one workspace install;
arbitrary JSON values
- **`GLOBAL`**: entries are shared across every install of the app, with
claim semantics — the value is always the claiming `workspaceId` and
only that workspace can overwrite or delete the key (guarded writes,
race-safe via insert-if-absent)

Since `applicationId` identifies an install (one row per workspace),
GLOBAL entries are stored under the registration owner workspace's
install so all installs of the same app share one namespace.

The GLOBAL scope is what enables cross-workspace webhook routing: e.g.
the Slack app's `serverRoute` resolver (running in the owner workspace)
can resolve `kv.get('slack:team:' + team_id, { scope: 'GLOBAL' })` to
find the workspace that connected that Slack team — without a workspace
being able to hijack another's mapping.

## Follow-ups

- Wire the Slack assistant PR (#22984) to write the claim at connect
time and read it in the events resolver
- `kv.*` access from front components

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23089?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-07-22 11:19:44 +02:00
martmull 21c3574f05 docs(apps): add key-value store guide for logic functions (#22061)
## What

Adds a new docs page under **Developers → Extend → Apps → Logic**
explaining how to give logic functions key-value storage (to persist
intermediate results, cache data, and share state across runs).

Rather than introducing a dedicated storage primitive, the guide shows
how to achieve this with a small **technical object** ("KV Store") that
has a unique `key` field and a `RAW_JSON` `value` field — queried
through the existing typed `CoreApiClient`.

Closes the documentation part of
[core-team-issues#2427](https://github.com/twentyhq/core-team-issues/issues/2427).

## Contents of the new page

- `defineObject` for the `kvStore` object (`key` + `value`)
- A unique index on `key` (the recommended uniqueness primitive)
- `get` / `set` (upsert) / `del` helpers built on `CoreApiClient`
- A worked example: caching an expensive third-party call with a TTL
- Patterns & tips: namespacing, expiry, what to store,
visibility/permissions, per-record scoping

## Files

- `developers/extend/apps/logic/key-value-store.mdx` — the new page
- `navigation/base-structure.json` — navigation source-of-truth
- `docs.json` + `twenty-shared/.../DocumentationPaths.ts` — regenerated
from base-structure

## Notes

- Documentation only — no code/behavior changes.
- This is a convention (a regular custom object), not a new feature, so
it inherits the same sync, permissions, and tooling as the rest of an
app's data.

https://claude.ai/code/session_01XAgXy1mUUMff5BFkFPjtfZ

---
_Generated by [Claude
Code](https://claude.ai/code/session_01XAgXy1mUUMff5BFkFPjtfZ)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22061?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-24 11:45:35 +02:00