n8n-nodes-lifespace 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shirui Huang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # n8n-nodes-lifespace
2
+
3
+ Official n8n community nodes for integrating workflows and AI agents with LifeSpace.
4
+
5
+ ## Status
6
+
7
+ The package currently provides:
8
+
9
+ - a LifeSpace Connection credential using a Connection Base URL plus an opaque `lsp_pat_*` Service API Token;
10
+ - a LifeSpace Webhook credential for storing event-subscription signing secrets outside workflow parameters;
11
+ - a LifeSpace node with generic Model Record operations plus an advanced connection-relative API request escape hatch;
12
+ - discovery-driven Model, Action, Create/Update field, Query and Action Input UX against the connection's current LifeSpace authority;
13
+ - a LifeSpace Trigger that receives signed LifeSpace domain-event webhooks;
14
+ - the official `n8n-node` development toolchain;
15
+ - CI for lint and build validation;
16
+ - a GitHub Actions npm publishing path with provenance support.
17
+
18
+ Domain-specific UX and AI-tool surfaces will be added only against stable upstream LifeSpace contracts/discovery metadata.
19
+
20
+ ## Architecture boundary
21
+
22
+ LifeSpace is the source of truth for identity, authorization, domain models, contracts and events. This repository is an n8n-specific adapter and must not become a second copy of LifeSpace business contracts.
23
+
24
+ LifeSpace does not depend on n8n. n8n is one optional orchestration and integration runtime that consumes LifeSpace APIs and events.
25
+
26
+ ## Development
27
+
28
+ Requirements:
29
+
30
+ - Node.js 22.22.0 or newer;
31
+ - npm;
32
+ - a local n8n instance for interactive node testing.
33
+
34
+ Install and validate:
35
+
36
+ ```bash
37
+ npm install
38
+ npm run lint
39
+ npm run build
40
+ ```
41
+
42
+ Run the node in a local n8n development instance:
43
+
44
+ ```bash
45
+ npm run dev
46
+ ```
47
+
48
+ ## Credentials
49
+
50
+ Create and authorize the integration in LifeSpace Web first. The Web configuration owns the target Space and its granted model permissions, then exposes the values to copy into n8n:
51
+
52
+ - **Connection Base URL**, for example `https://core.aisr.online/api/v1/spaces/spc_...`;
53
+ - **Service API Token**, an opaque `lsp_pat_*` token issued for that connection.
54
+
55
+ The Credential represents one already-configured LifeSpace connection. Individual LifeSpace nodes therefore do not ask for a Space ID.
56
+
57
+ The Connection Base URL carries routing context only. Authorization still comes from the Service API Token plus LifeSpace credential scopes, Application × Model Access and current Space/Data Grant authority. Revoking the token or grant invalidates the connection without changing the n8n workflow.
58
+
59
+ Do not store real tokens in source code, workflow examples or repository files.
60
+
61
+ ## LifeSpace Model Record
62
+
63
+ The **Model Record** resource is a thin adapter over LifeSpace Generic Runtime routes. It supports:
64
+
65
+ - Create;
66
+ - Get;
67
+ - List / Query;
68
+ - Update with optimistic concurrency;
69
+ - Delete with optimistic concurrency;
70
+ - Execute Action for published Capability/workflow actions.
71
+
72
+ The node loads its Model selector from `{Connection Base URL}/_discovery`. The list contains only models the current connection can currently use after LifeSpace applies credential scopes, Application × Model Access and current Space membership/Data Grants. The **Action** selector is then loaded dynamically from the selected model and is filtered by the same discovery authority.
73
+
74
+ ### Discovery-driven fields
75
+
76
+ Create and Update use n8n's resource-mapper UI driven directly by the selected model's bounded Runtime Discovery metadata instead of a handwritten `Fields (JSON)` contract.
77
+
78
+ - required Create fields follow LifeSpace field metadata;
79
+ - read-only fields are excluded;
80
+ - immutable fields are additionally excluded from Update;
81
+ - enum fields render as options;
82
+ - number, boolean, datetime and list fields use the corresponding n8n input types;
83
+ - LifeSpace date-only fields intentionally remain strings so `YYYY-MM-DD` values are never converted into timezone-bearing instants;
84
+ - automatic input-data mapping is intentionally disabled for now so unrelated incoming keys are not silently sent to LifeSpace's strict model schema.
85
+
86
+ ### Discovery-driven query
87
+
88
+ List / Query uses bounded query metadata from LifeSpace Runtime Discovery rather than a free-form JSON request.
89
+
90
+ - searchable fields enable the Search input only where the model declares search support;
91
+ - filter fields are limited to the model's published filterable fields;
92
+ - equality and supported range operators map to LifeSpace Generic Runtime query parameters;
93
+ - sort fields are limited to published sortable fields;
94
+ - pagination uses the LifeSpace `limit` and opaque `cursor` contract;
95
+ - the node does not invent query operators or field semantics that are absent from upstream Discovery metadata.
96
+
97
+ ### Discovery-driven Action Input
98
+
99
+ Execute Action uses a second resource-mapper driven by the selected action's bounded input metadata from LifeSpace Runtime Discovery.
100
+
101
+ - Model Definition v1 workflow actions currently expose the optimistic-concurrency `version` input;
102
+ - the `record-occurrence` Capability action exposes `version`, `occurredOn` and optional `note` according to the upstream contract;
103
+ - required/optional status, primitive input types, date-only handling and length/range constraints come from LifeSpace metadata;
104
+ - the node does not copy action schemas into this package or accept an unrestricted Action Input JSON object for normal use.
105
+
106
+ LifeSpace Core remains authoritative for validation and authorization when an operation executes. Runtime Discovery is a dynamic UX/capability preview, not an execution-authorization proof.
107
+
108
+ The node does not use the privileged `model-admin/contracts/*` surface for ordinary workflow discovery and does not copy model definitions into this repository.
109
+
110
+ The **API Request** resource remains available as an advanced escape hatch for paths relative to the configured Connection Base URL.
111
+
112
+ ## LifeSpace Trigger
113
+
114
+ LifeSpace event subscriptions are currently managed by an authenticated LifeSpace user with Space-management permission. A service token intentionally cannot create or modify subscriptions.
115
+
116
+ To use the trigger:
117
+
118
+ 1. add a LifeSpace Trigger to an n8n workflow and activate the workflow;
119
+ 2. copy the node's production webhook URL;
120
+ 3. create a LifeSpace Webhook Endpoint for the target Space and use that URL as its destination;
121
+ 4. attach one or more LifeSpace Event Subscription filters for the required model/events to that endpoint;
122
+ 5. create a **LifeSpace Webhook API** credential and store the endpoint's one-time signing secret in that credential;
123
+ 6. attach the credential to the Trigger and optionally set expected Space/model filters as an additional local check;
124
+ 7. use LifeSpace's endpoint test action to verify delivery.
125
+
126
+ The signing secret is intentionally stored as an n8n Credential rather than as a workflow parameter. Workflow exports therefore reference the credential instead of embedding the secret as ordinary node configuration.
127
+
128
+ The trigger validates `X-LifeSpace-Timestamp` and `X-LifeSpace-Signature` using the upstream LifeSpace HMAC-SHA256 contract before emitting workflow data.
129
+
130
+ ## Publishing and verification
131
+
132
+ This repository is public and is intended to remain eligible for n8n community-node verification.
133
+
134
+ Publishing is performed only by `.github/workflows/publish.yml` from a version tag matching `*.*.*`. The workflow grants only `contents: read` plus `id-token: write`, so npm can attach a provenance attestation to the public package.
135
+
136
+ Preferred npm authentication is Trusted Publishing through GitHub Actions. A scoped `NPM_TOKEN` is supported only as a fallback. Do not publish a verification candidate directly from a developer workstation.
137
+
138
+ Before the first npm release:
139
+
140
+ 1. ensure the `n8n-nodes-lifespace` package is available to the publishing npm account;
141
+ 2. configure npm Trusted Publishing for `huangshirui/lifespace-n8n-nodes` and workflow `publish.yml`, or install a narrowly scoped fallback `NPM_TOKEN`;
142
+ 3. ensure CI passes on the exact release commit;
143
+ 4. create the release through the `n8n-node` release flow so the pushed version tag triggers the provenance workflow;
144
+ 5. verify the npm package links back to this public GitHub repository and exposes the MIT license and expected node metadata.
145
+
146
+ The package intentionally has no runtime `dependencies`. It must not read environment variables or the local filesystem. Node UI, help text, errors, README content and examples remain English-only for n8n verification compatibility.
147
+
148
+ ## Planned surfaces
149
+
150
+ - richer relation selectors when LifeSpace exposes an appropriate authorized lookup surface;
151
+ - a more explicit n8n AI Tool experience for approved LifeSpace actions if the generic tool-capable node proves insufficient;
152
+ - delegated Webhook Endpoint / Event Subscription management if LifeSpace later exposes an appropriate user-authorized integration contract;
153
+ - OAuth `client_credentials` support where required.
154
+
155
+ ## License
156
+
157
+ MIT
@@ -0,0 +1,10 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class LifeSpaceApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ icon: "file:lifespace.svg";
6
+ documentationUrl: string;
7
+ properties: INodeProperties[];
8
+ authenticate: IAuthenticateGeneric;
9
+ test: ICredentialTestRequest;
10
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LifeSpaceApi = void 0;
4
+ class LifeSpaceApi {
5
+ constructor() {
6
+ this.name = 'lifeSpaceApi';
7
+ this.displayName = 'LifeSpace Connection API';
8
+ this.icon = 'file:lifespace.svg';
9
+ this.documentationUrl = 'https://github.com/huangshirui/LifeSpace';
10
+ this.properties = [
11
+ {
12
+ displayName: 'Connection Base URL',
13
+ name: 'baseUrl',
14
+ type: 'string',
15
+ default: '',
16
+ placeholder: 'https://core.aisr.online/api/v1/spaces/spc_...',
17
+ required: true,
18
+ description: 'Copy the Connection Base URL from the LifeSpace Web integration configuration',
19
+ },
20
+ {
21
+ displayName: 'Service API Token',
22
+ name: 'token',
23
+ type: 'string',
24
+ typeOptions: { password: true },
25
+ default: '',
26
+ required: true,
27
+ description: 'Copy the LifeSpace Service API Token (lsp_pat_*) issued for this connection',
28
+ },
29
+ ];
30
+ this.authenticate = {
31
+ type: 'generic',
32
+ properties: {
33
+ headers: {
34
+ Authorization: '=Bearer {{$credentials.token}}',
35
+ },
36
+ },
37
+ };
38
+ this.test = {
39
+ request: {
40
+ baseURL: '={{$credentials.baseUrl.replace(/\\/$/, "")}}',
41
+ url: '/_discovery',
42
+ method: 'GET',
43
+ },
44
+ };
45
+ }
46
+ }
47
+ exports.LifeSpaceApi = LifeSpaceApi;
48
+ //# sourceMappingURL=LifeSpaceApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LifeSpaceApi.credentials.js","sourceRoot":"","sources":["../../credentials/LifeSpaceApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,YAAY;IAAzB;QACE,SAAI,GAAG,cAAc,CAAC;QAEtB,gBAAW,GAAG,0BAA0B,CAAC;QAEzC,SAAI,GAAG,oBAA6B,CAAC;QAErC,qBAAgB,GAAG,0CAA0C,CAAC;QAE9D,eAAU,GAAsB;YAC9B;gBACE,WAAW,EAAE,qBAAqB;gBAClC,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,gDAAgD;gBAC7D,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,+EAA+E;aAC7F;YACD;gBACE,WAAW,EAAE,mBAAmB;gBAChC,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,6EAA6E;aAC3F;SACF,CAAC;QAEF,iBAAY,GAAyB;YACnC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACV,OAAO,EAAE;oBACP,aAAa,EAAE,gCAAgC;iBAChD;aACF;SACF,CAAC;QAEF,SAAI,GAA2B;YAC7B,OAAO,EAAE;gBACP,OAAO,EAAE,+CAA+C;gBACxD,GAAG,EAAE,aAAa;gBAClB,MAAM,EAAE,KAAK;aACd;SACF,CAAC;IACJ,CAAC;CAAA;AA9CD,oCA8CC"}
@@ -0,0 +1,8 @@
1
+ import type { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class LifeSpaceWebhookApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ icon: "file:lifespace.svg";
6
+ documentationUrl: string;
7
+ properties: INodeProperties[];
8
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LifeSpaceWebhookApi = void 0;
4
+ class LifeSpaceWebhookApi {
5
+ constructor() {
6
+ this.name = 'lifeSpaceWebhookApi';
7
+ this.displayName = 'LifeSpace Webhook API';
8
+ this.icon = 'file:lifespace.svg';
9
+ this.documentationUrl = 'https://github.com/huangshirui/lifespace-n8n-nodes#lifespace-trigger';
10
+ this.properties = [
11
+ {
12
+ displayName: 'Signing Secret',
13
+ name: 'signingSecret',
14
+ type: 'string',
15
+ typeOptions: { password: true },
16
+ default: '',
17
+ required: true,
18
+ description: 'One-time signing secret returned when the LifeSpace event subscription is created or rotated',
19
+ },
20
+ ];
21
+ }
22
+ }
23
+ exports.LifeSpaceWebhookApi = LifeSpaceWebhookApi;
24
+ //# sourceMappingURL=LifeSpaceWebhookApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LifeSpaceWebhookApi.credentials.js","sourceRoot":"","sources":["../../credentials/LifeSpaceWebhookApi.credentials.ts"],"names":[],"mappings":";;;AAEA,MAAa,mBAAmB;IAAhC;QACE,SAAI,GAAG,qBAAqB,CAAC;QAE7B,gBAAW,GAAG,uBAAuB,CAAC;QAEtC,SAAI,GAAG,oBAA6B,CAAC;QAErC,qBAAgB,GAAG,sEAAsE,CAAC;QAE1F,eAAU,GAAsB;YAC9B;gBACE,WAAW,EAAE,gBAAgB;gBAC7B,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,8FAA8F;aAC5G;SACF,CAAC;IACJ,CAAC;CAAA;AApBD,kDAoBC"}
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="LifeSpace">
2
+ <defs>
3
+ <linearGradient id="lifespace-bg" x1="7" y1="57" x2="57" y2="7" gradientUnits="userSpaceOnUse">
4
+ <stop offset="0" stop-color="#075FEA"/>
5
+ <stop offset="0.55" stop-color="#087CF5"/>
6
+ <stop offset="1" stop-color="#25A8FF"/>
7
+ </linearGradient>
8
+ </defs>
9
+ <rect width="64" height="64" rx="14" fill="url(#lifespace-bg)"/>
10
+ <g fill="none" stroke="#FFFFFF" stroke-width="5" stroke-linecap="round" stroke-linejoin="round">
11
+ <path d="M29 14.5 19 20.5a5 5 0 0 0-2.5 4.3v14.4a5 5 0 0 0 2.5 4.3l10 6"/>
12
+ <path d="M35 14.5 45 20.5a5 5 0 0 1 2.5 4.3v14.4a5 5 0 0 1-2.5 4.3l-10 6"/>
13
+ </g>
14
+ <circle cx="32" cy="32" r="4.6" fill="#FFFFFF"/>
15
+ </svg>
@@ -0,0 +1,17 @@
1
+ import type { IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription, ResourceMapperFields } from 'n8n-workflow';
2
+ export declare class LifeSpace implements INodeType {
3
+ description: INodeTypeDescription;
4
+ methods: {
5
+ loadOptions: {
6
+ getModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
+ getActions(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
8
+ getFilterableFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
9
+ getSortableFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
10
+ };
11
+ resourceMapping: {
12
+ getModelFields(this: ILoadOptionsFunctions): Promise<ResourceMapperFields>;
13
+ getActionInputFields(this: ILoadOptionsFunctions): Promise<ResourceMapperFields>;
14
+ };
15
+ };
16
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
17
+ }