@idp.global/sdk 1.2.0 → 1.3.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/changelog.md +10 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/package.json +7 -7
- package/readme.md +295 -5
- package/ts/00_commitinfo_data.ts +1 -1
package/changelog.md
CHANGED
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
|
|
8
|
+
## 2026-05-18 - 1.3.0
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
- publish @idp.global/interfaces dependency and expand SDK usage documentation (docs,deps)
|
|
13
|
+
- replace the local file-based @idp.global/interfaces dependency with the published ^1.0.1 package
|
|
14
|
+
- refresh development tooling versions in package.json
|
|
15
|
+
- rewrite the README with detailed browser and server SDK installation, API, and usage guidance
|
|
16
|
+
|
|
7
17
|
## 2026-05-13 - 1.2.0
|
|
8
18
|
|
|
9
19
|
### Features
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@idp.global/sdk',
|
|
6
|
-
version: '1.
|
|
6
|
+
version: '1.3.0',
|
|
7
7
|
description: 'Reusable browser and server SDK for idp.global authentication.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxpQkFBaUI7SUFDdkIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLGdFQUFnRTtDQUM5RSxDQUFBIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idp.global/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Reusable browser and server SDK for idp.global authentication.",
|
|
6
6
|
"type": "module",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@api.global/typedrequest": "^3.3.0",
|
|
18
18
|
"@api.global/typedsocket": "^4.1.2",
|
|
19
|
-
"@idp.global/interfaces": "
|
|
19
|
+
"@idp.global/interfaces": "^1.0.1",
|
|
20
20
|
"@push.rocks/smartdata": "^7.1.7",
|
|
21
21
|
"@push.rocks/smartjson": "^6.0.1",
|
|
22
22
|
"@push.rocks/smartpromise": "^4.2.4",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"@push.rocks/webstore": "^2.0.22"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@git.zone/tsbuild": "^4.4.
|
|
31
|
-
"@git.zone/tsdoc": "^2.0.
|
|
32
|
-
"@git.zone/tsrun": "^2.0.
|
|
33
|
-
"@git.zone/tstest": "^3.6.
|
|
30
|
+
"@git.zone/tsbuild": "^4.4.1",
|
|
31
|
+
"@git.zone/tsdoc": "^2.0.5",
|
|
32
|
+
"@git.zone/tsrun": "^2.0.4",
|
|
33
|
+
"@git.zone/tstest": "^3.6.6",
|
|
34
34
|
"@push.rocks/smartdb": "^2.10.0",
|
|
35
|
-
"@types/node": "^25.
|
|
35
|
+
"@types/node": "^25.9.0"
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"ts/**/*",
|
package/readme.md
CHANGED
|
@@ -1,10 +1,300 @@
|
|
|
1
1
|
# @idp.global/sdk
|
|
2
2
|
|
|
3
|
-
Reusable SDK for idp.global browser
|
|
3
|
+
Reusable TypeScript SDK for building against idp.global from both sides of the wire: browser apps that need SSO, JWT housekeeping, transfer-token handoff, and typed IdP requests; and server apps that need explicit account storage, local password auth, and optional idp.global password verification.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The package is intentionally split by runtime. Use `@idp.global/sdk/browser` in browser bundles and `@idp.global/sdk/server` in Node.js services. The root `@idp.global/sdk` export does not expose application APIs.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- `@idp.global/sdk/server`
|
|
7
|
+
## Issue Reporting and Security
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
10
|
+
|
|
11
|
+
## What You Get
|
|
12
|
+
|
|
13
|
+
| Runtime | Import | What it does |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Browser | `@idp.global/sdk/browser` | SSO client, JWT and refresh-token storage, login redirects, logout, transfer-token exchange, and typed request shortcuts for user, organization, billing, OIDC, and admin flows. |
|
|
16
|
+
| Server | `@idp.global/sdk/server` | Smartdata-backed account store, scrypt password hashing, local/idp.global account authentication, and a server-side typed-socket client for idp.global password login. |
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @idp.global/sdk
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This is an ESM TypeScript package. Published builds expose declaration files and runtime JavaScript through package exports.
|
|
25
|
+
|
|
26
|
+
## Browser SDK
|
|
27
|
+
|
|
28
|
+
Import the browser client from the browser subpath:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { IdpClient } from '@idp.global/sdk/browser';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Create one client per app shell. The `receptionBaseUrl` may be the SSO origin or the full typedrequest URL; the SDK normalizes it to `/typedrequest` internally.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const idp = new IdpClient('https://sso.workspace.global', {
|
|
38
|
+
id: 'my-app',
|
|
39
|
+
name: 'My App',
|
|
40
|
+
description: 'The app your users actually want to open.',
|
|
41
|
+
logoUrl: 'https://app.example.com/logo.svg',
|
|
42
|
+
appUrl: 'https://app.example.com/',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await idp.enableTypedSocket();
|
|
46
|
+
|
|
47
|
+
const loggedIn = await idp.determineLoginStatus(true);
|
|
48
|
+
if (loggedIn) {
|
|
49
|
+
const whoIsResult = await idp.whoIs();
|
|
50
|
+
console.log(whoIsResult.user);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
When `determineLoginStatus(true)` cannot recover a valid JWT from browser storage, a refresh token, or a `transfertoken` query parameter, it redirects the user to the configured idp.global login route with your app metadata encoded as `appdata`.
|
|
55
|
+
|
|
56
|
+
### Token Handling
|
|
57
|
+
|
|
58
|
+
The browser client stores auth state in `@push.rocks/webstore` using the `idpglobalStore` store and `main` database.
|
|
59
|
+
|
|
60
|
+
| Method | Purpose |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `setJwt(jwt)` / `getJwt()` / `deleteJwt()` | Manage the current JWT. |
|
|
63
|
+
| `setRefreshToken(token)` / `getRefreshToken()` / `deleteRefreshToken()` | Manage the refresh token. |
|
|
64
|
+
| `clearAuthState()` | Remove both JWT and refresh token. |
|
|
65
|
+
| `getJwtData()` | Decode the current JWT through `@push.rocks/webjwt`. |
|
|
66
|
+
| `performJwtHousekeeping()` | Refresh a JWT after its `refreshFrom` timestamp or recover from an expired JWT through the refresh token. |
|
|
67
|
+
| `refreshJwt(refreshToken?)` | Exchange a refresh token for a fresh JWT and update stored auth state. |
|
|
68
|
+
| `checkJwtPresent()` | Return whether a usable JWT can be found or refreshed. |
|
|
69
|
+
|
|
70
|
+
### Login With Username And Password
|
|
71
|
+
|
|
72
|
+
The browser request wrappers are typed request factories. Call `enableTypedSocket()` before firing them.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
await idp.enableTypedSocket();
|
|
76
|
+
|
|
77
|
+
const loginResponse = await idp.requests.loginWithUserNameAndPassword.fire({
|
|
78
|
+
username: 'developer@example.com',
|
|
79
|
+
password: 'correct horse battery staple',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (loginResponse.twoFaNeeded) {
|
|
83
|
+
throw new Error('Two-factor authentication is required for this account.');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (loginResponse.refreshToken) {
|
|
87
|
+
await idp.setRefreshToken(loginResponse.refreshToken);
|
|
88
|
+
await idp.refreshJwt(loginResponse.refreshToken);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Transfer Tokens
|
|
93
|
+
|
|
94
|
+
Transfer tokens are the handoff mechanism for moving a logged-in user between apps without exposing refresh tokens to URLs.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const transferToken = await idp.getTransferToken();
|
|
98
|
+
if (transferToken) {
|
|
99
|
+
const target = new URL('https://another-app.example.com/');
|
|
100
|
+
target.searchParams.set('transfertoken', transferToken);
|
|
101
|
+
window.location.href = target.toString();
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
On the receiving app, `determineLoginStatus()` calls `processTransferToken()` as part of its normal recovery flow. You can also call `processTransferToken()` directly when you own the route handling.
|
|
106
|
+
|
|
107
|
+
### Logout
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
await idp.logout();
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`logout()` clears local auth state and, when a refresh token is available on the SSO origin, asks idp.global to revoke the session before returning the user to the original app URL when app metadata is present.
|
|
114
|
+
|
|
115
|
+
### Browser API Surface
|
|
116
|
+
|
|
117
|
+
| API | Description |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| `new IdpClient(receptionBaseUrl, appData?)` | Configure an idp.global browser client. |
|
|
120
|
+
| `enableTypedSocket()` / `stop()` | Start or stop the typed-socket connection. |
|
|
121
|
+
| `determineLoginStatus(requireLogin?)` | Resolve login state from JWT, refresh token, transfer token, or optional redirect. |
|
|
122
|
+
| `statusObservable` | RxJS subject that emits idp.global login status changes during refresh flows. |
|
|
123
|
+
| `whoIs()` | Resolve the current user through the active JWT. |
|
|
124
|
+
| `getRolesAndOrganizations()` | Fetch roles and organizations for the current user. |
|
|
125
|
+
| `createOrganization(name, slug, mode)` | Check organization slug availability or manifest an organization. |
|
|
126
|
+
| `updatePaddleCheckoutId(orgId, checkoutId)` | Send a Paddle checkout ID as the org payment method update. |
|
|
127
|
+
| `getTransferToken(appData?)` | Exchange the current refresh token for a transfer token. |
|
|
128
|
+
| `getTransferTokenAndSwitchToLocation(url)` | Create a transfer token and redirect with `transfertoken` attached. |
|
|
129
|
+
| `processTransferToken()` | Consume a `transfertoken` from the current URL and refresh local auth state. |
|
|
130
|
+
| `logout()` | Revoke and clear the current login flow. |
|
|
131
|
+
|
|
132
|
+
### Typed Request Shortcuts
|
|
133
|
+
|
|
134
|
+
`idp.requests` exposes typed request factories backed by `@idp.global/interfaces`. The request and response payload types come from that package, so your editor can guide exact payload shapes.
|
|
135
|
+
|
|
136
|
+
| Area | Request getters |
|
|
137
|
+
| --- | --- |
|
|
138
|
+
| Registration and login | `firstRegistration`, `afterRegistrationEmailClicked`, `setData`, `mobileNumberVerification`, `finishRegistration`, `loginWithUserNameAndPassword`, `loginWithEmail`, `loginWithEmailAfterToken`, `loginWithApiToken`, `resetPassword`, `setNewPassword`, `obtainDeviceId`, `attachDeviceId` |
|
|
139
|
+
| Tokens and OIDC | `obtainJwt`, `obtainOneTimeToken`, `prepareOidcAuthorization`, `completeOidcAuthorization` |
|
|
140
|
+
| User profile and sessions | `getUserData`, `setUserData`, `getUserSessions`, `revokeSession`, `getUserActivity` |
|
|
141
|
+
| Organizations and members | `getOrganizationById`, `updateOrganization`, `deleteOrganization`, `getOrgRoleDefinitions`, `upsertOrgRoleDefinition`, `deleteOrgRoleDefinition`, `createInvitation`, `getOrgInvitations`, `getOrgMembers`, `cancelInvitation`, `resendInvitation`, `removeMember`, `updateMemberRoles`, `transferOwnership`, `getInvitationByToken`, `acceptInvitation`, `bulkCreateInvitations`, `updateAppRoleMappings` |
|
|
142
|
+
| Billing and validation | `getBillingPlan`, `getPaddleConfig`, `getPublicKeyForValidation`, `pushPublicKeyForValidation`, `pushOrGetJwtIdBlocklist` |
|
|
143
|
+
| Global administration | `suspendUser`, `deleteSuspendedUser`, `checkGlobalAdmin`, `getGlobalAppStats`, `createGlobalApp`, `updateGlobalApp`, `deleteGlobalApp`, `regenerateAppCredentials` |
|
|
144
|
+
|
|
145
|
+
## Server SDK
|
|
146
|
+
|
|
147
|
+
Import server-side primitives from the server subpath:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import {
|
|
151
|
+
AccountAuthService,
|
|
152
|
+
IdpGlobalServerClient,
|
|
153
|
+
SmartdataAccountStore,
|
|
154
|
+
} from '@idp.global/sdk/server';
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The server SDK is deliberately explicit: it never auto-creates accounts during authentication. Your application decides when an account exists, which auth sources it may use, and whether it is an `admin` or `user`.
|
|
158
|
+
|
|
159
|
+
### Smartdata Account Store
|
|
160
|
+
|
|
161
|
+
`SmartdataAccountStore` persists accounts through `@push.rocks/smartdata` and the exported `IdpSdkAccountDoc` collection.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import * as smartdata from '@push.rocks/smartdata';
|
|
165
|
+
import { SmartdataAccountStore } from '@idp.global/sdk/server';
|
|
166
|
+
|
|
167
|
+
const smartdataDb = new smartdata.SmartdataDb({
|
|
168
|
+
mongoDbUrl: process.env.MONGODB_URL!,
|
|
169
|
+
mongoDbName: 'my-app',
|
|
170
|
+
});
|
|
171
|
+
await smartdataDb.init();
|
|
172
|
+
|
|
173
|
+
const accountStore = new SmartdataAccountStore({ smartdataDb });
|
|
174
|
+
|
|
175
|
+
if (!(await accountStore.hasActiveAdminAccount())) {
|
|
176
|
+
await accountStore.createAccount({
|
|
177
|
+
email: 'admin@example.com',
|
|
178
|
+
name: 'Admin User',
|
|
179
|
+
role: 'admin',
|
|
180
|
+
authSources: ['local'],
|
|
181
|
+
password: process.env.INITIAL_ADMIN_PASSWORD!,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Account emails are trimmed and normalized to lowercase for lookups. Local passwords are hashed with Node.js `crypto.scrypt`, a random salt, and timing-safe verification.
|
|
187
|
+
|
|
188
|
+
| Method | Purpose |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `createAccount(options)` | Persist an explicitly created account. Requires a password when `authSources` includes `local`. |
|
|
191
|
+
| `getAccountByEmail(email)` | Find an account by normalized email. |
|
|
192
|
+
| `getAccountById(id)` | Find an account by UUID. |
|
|
193
|
+
| `listAccounts()` | Return all persisted accounts. |
|
|
194
|
+
| `hasActiveAdminAccount()` | Return whether at least one active admin account exists. |
|
|
195
|
+
| `verifyLocalPassword(account, password)` | Validate a local password for an active local account. |
|
|
196
|
+
| `updateLoginState(accountId, patch)` | Update `lastLoginAt`, `updatedAt`, and optionally `idpSubject`. |
|
|
197
|
+
| `normalizeEmail(email)` | Normalize an email exactly like the store does internally. |
|
|
198
|
+
|
|
199
|
+
### Account Authentication
|
|
200
|
+
|
|
201
|
+
`AccountAuthService` authenticates only existing active accounts. It supports local passwords, idp.global passwords, or `auto` mode.
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import {
|
|
205
|
+
AccountAuthService,
|
|
206
|
+
IdpGlobalServerClient,
|
|
207
|
+
SmartdataAccountStore,
|
|
208
|
+
} from '@idp.global/sdk/server';
|
|
209
|
+
|
|
210
|
+
const accountStore = new SmartdataAccountStore({ smartdataDb });
|
|
211
|
+
const idpClient = new IdpGlobalServerClient({
|
|
212
|
+
baseUrl: 'https://sso.workspace.global',
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const authService = new AccountAuthService({
|
|
216
|
+
store: accountStore,
|
|
217
|
+
idpClient,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const authResult = await authService.authenticate({
|
|
221
|
+
email: 'admin@example.com',
|
|
222
|
+
password: 'correct horse battery staple',
|
|
223
|
+
authSource: 'auto',
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (!authResult) {
|
|
227
|
+
throw new Error('Invalid login.');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
console.log(authResult.account.role, authResult.authSource);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
In `auto` mode, the service tries local auth first when the account allows `local`; if that fails and the account allows `idp.global`, it uses the configured `IdpGlobalServerClient`. idp.global authentication is accepted only when the returned user email matches the local account email and the returned user ID matches the stored `idpSubject` when one is already set.
|
|
234
|
+
|
|
235
|
+
### Server API Surface
|
|
236
|
+
|
|
237
|
+
| API | Description |
|
|
238
|
+
| --- | --- |
|
|
239
|
+
| `SmartdataAccountStore` | Smartdata-backed account persistence and local password verification. |
|
|
240
|
+
| `AccountAuthService` | Existing-account authentication orchestration for `local`, `idp.global`, and `auto`. |
|
|
241
|
+
| `IdpGlobalServerClient` | Typed-socket client for idp.global password login, JWT refresh, and `whoIs` lookup. |
|
|
242
|
+
| `PasswordHasher` | Static `hashPassword()` and `verifyPassword()` helpers using `scrypt:v1`. |
|
|
243
|
+
| `IdpSdkAccountDoc` | Smartdata document class backing persisted SDK accounts. |
|
|
244
|
+
| `setAccountDocSmartdataDb()` | Configure the active Smartdata DB for `IdpSdkAccountDoc`. Usually handled by `SmartdataAccountStore`. |
|
|
245
|
+
|
|
246
|
+
### Types
|
|
247
|
+
|
|
248
|
+
The server export includes these TypeScript types:
|
|
249
|
+
|
|
250
|
+
| Type | Values or purpose |
|
|
251
|
+
| --- | --- |
|
|
252
|
+
| `TIdpAccountAuthSource` | `'local' | 'idp.global'` |
|
|
253
|
+
| `TIdpAccountRole` | `'admin' | 'user'` |
|
|
254
|
+
| `TIdpAccountStatus` | `'active' | 'disabled'` |
|
|
255
|
+
| `IIdpSdkAccount` | Persisted account shape. |
|
|
256
|
+
| `ICreateIdpSdkAccountOptions` | Input for account creation. |
|
|
257
|
+
| `IAuthenticateAccountOptions` | Input for `AccountAuthService.authenticate()`. |
|
|
258
|
+
| `IAuthenticatedAccountResult` | Successful auth result with account, auth source, and optional idp.global tokens. |
|
|
259
|
+
| `IIdpGlobalServerClientOptions` | Server client configuration with `baseUrl`. |
|
|
260
|
+
| `IIdpPasswordAuthResult` | idp.global user, JWT, and refresh-token result. |
|
|
261
|
+
|
|
262
|
+
## Runtime Notes
|
|
263
|
+
|
|
264
|
+
Use the explicit subpath imports. They keep browser bundles free of Node-only code and keep server processes free of browser storage dependencies.
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import { IdpClient } from '@idp.global/sdk/browser';
|
|
268
|
+
import { AccountAuthService } from '@idp.global/sdk/server';
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
The SDK uses typed sockets and typed requests from `@api.global/*`, shared idp.global request contracts from `@idp.global/interfaces`, and focused Push Rocks utilities for URL handling, JSON/base64 encoding, observables, JWT decoding, browser storage, smartdata persistence, and promise coordination.
|
|
272
|
+
|
|
273
|
+
## Testing
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
pnpm test
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The test suite currently covers the server account store and auth service: explicit account creation, scrypt-backed local password verification, active-admin detection, and rejection of idp.global login results that do not match the persisted account email.
|
|
280
|
+
|
|
281
|
+
## License and Legal Information
|
|
282
|
+
|
|
283
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
|
|
284
|
+
|
|
285
|
+
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
286
|
+
|
|
287
|
+
### Trademarks
|
|
288
|
+
|
|
289
|
+
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|
290
|
+
|
|
291
|
+
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|
292
|
+
|
|
293
|
+
### Company Information
|
|
294
|
+
|
|
295
|
+
Task Venture Capital GmbH<br>
|
|
296
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
297
|
+
|
|
298
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
299
|
+
|
|
300
|
+
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|