First commit
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
|
||||||
|
"changelog": "@changesets/cli/changelog",
|
||||||
|
"commit": false,
|
||||||
|
"fixed": [],
|
||||||
|
"linked": [],
|
||||||
|
"access": "restricted",
|
||||||
|
"baseBranch": "main",
|
||||||
|
"updateInternalDependencies": "patch",
|
||||||
|
"ignore": [
|
||||||
|
"lynkedup-pro",
|
||||||
|
"lynkedup-foundation",
|
||||||
|
"api-bff",
|
||||||
|
"sdk-playground"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
ignorePatterns: ['**/*'],
|
||||||
|
plugins: ['@nx'],
|
||||||
|
extends: ['@react-native'],
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
||||||
|
rules: {
|
||||||
|
'@nx/enforce-module-boundaries': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
enforceBuildableLibDependency: true,
|
||||||
|
allow: [],
|
||||||
|
depConstraints: [
|
||||||
|
// Domain Purity: Domain layers can only depend on other domain layers or types
|
||||||
|
{
|
||||||
|
sourceTag: 'type:domain',
|
||||||
|
onlyDependOnLibsWithTags: ['type:domain', 'type:types', 'scope:shared']
|
||||||
|
},
|
||||||
|
|
||||||
|
// Data layer can depend on domain and core infrastructure
|
||||||
|
{
|
||||||
|
sourceTag: 'type:data',
|
||||||
|
onlyDependOnLibsWithTags: [
|
||||||
|
'type:domain',
|
||||||
|
'type:types',
|
||||||
|
'scope:core',
|
||||||
|
'scope:shared'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// UI layer can depend on data and domain
|
||||||
|
{
|
||||||
|
sourceTag: 'type:ui',
|
||||||
|
onlyDependOnLibsWithTags: [
|
||||||
|
'type:data',
|
||||||
|
'type:domain',
|
||||||
|
'type:types',
|
||||||
|
'scope:shared'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Platform-specific rules
|
||||||
|
{
|
||||||
|
sourceTag: 'platform:shared',
|
||||||
|
notDependOnLibsWithTags: ['platform:rn', 'platform:node']
|
||||||
|
},
|
||||||
|
|
||||||
|
// Vertical isolation: Features cannot depend on other features
|
||||||
|
{
|
||||||
|
sourceTag: 'scope:feature',
|
||||||
|
notDependOnLibsWithTags: ['scope:feature']
|
||||||
|
},
|
||||||
|
|
||||||
|
// Core SDKs can only depend on other core SDKs or shared
|
||||||
|
{
|
||||||
|
sourceTag: 'scope:core',
|
||||||
|
onlyDependOnLibsWithTags: ['scope:core', 'scope:shared', 'type:types']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.ts', '*.tsx'],
|
||||||
|
extends: ['@nx/typescript'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'warn'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.js', '*.jsx'],
|
||||||
|
extends: ['@nx/javascript'],
|
||||||
|
rules: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.spec.ts', '*.spec.tsx', '*.spec.js', '*.spec.jsx'],
|
||||||
|
env: {
|
||||||
|
jest: true
|
||||||
|
},
|
||||||
|
rules: {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
node_modules
|
||||||
|
/apps/lynkedup-pro
|
||||||
|
/apps/lynkedup-foundation
|
||||||
|
/apps/sdk-playground
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
'**/*.{ts,tsx,js,jsx}': [
|
||||||
|
'eslint',
|
||||||
|
'prettier --write'
|
||||||
|
],
|
||||||
|
'**/*.{json,md,yml,yaml}': [
|
||||||
|
'prettier --write'
|
||||||
|
],
|
||||||
|
'**/*.ts?(x)': () => 'nx affected -t typecheck'
|
||||||
|
};
|
||||||
BIN
Binary file not shown.
Vendored
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+23
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "nx-cloud-client-bundle",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"type": "commonjs",
|
||||||
|
"main": "index.js",
|
||||||
|
"author": "Victor Savkin",
|
||||||
|
"license": "proprietary",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "1.1.3",
|
||||||
|
"enquirer": "2.4.1",
|
||||||
|
"dotenv": "~10.0.0",
|
||||||
|
"node-machine-id": "^1.1.12",
|
||||||
|
"tar": "6.1.11",
|
||||||
|
"strip-json-comments": "^5.0.1",
|
||||||
|
"chalk": "4.1.2",
|
||||||
|
"yargs-parser": ">=21.1.1",
|
||||||
|
"fs-extra": "^11.1.0",
|
||||||
|
"open": "~8.4.0",
|
||||||
|
"ini": "4.1.3",
|
||||||
|
"yaml": "2.6.1",
|
||||||
|
"semver": "7.5.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
+414
@@ -0,0 +1,414 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Nx Cloud login</title>
|
||||||
|
<style>
|
||||||
|
*,
|
||||||
|
:before,
|
||||||
|
:after {
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
tab-size: 4;
|
||||||
|
font-family:
|
||||||
|
ui-sans-serif,
|
||||||
|
system-ui,
|
||||||
|
sans-serif,
|
||||||
|
'Apple Color Emoji',
|
||||||
|
'Segoe UI Emoji',
|
||||||
|
Segoe UI Symbol,
|
||||||
|
'Noto Color Emoji';
|
||||||
|
font-feature-settings: normal;
|
||||||
|
font-variation-settings: normal;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
line-height: inherit;
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(51 65 85 / var(--tw-text-opacity));
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-width: 0;
|
||||||
|
border-style: solid;
|
||||||
|
--tw-border-spacing-x: 0;
|
||||||
|
--tw-border-spacing-y: 0;
|
||||||
|
--tw-translate-x: 0;
|
||||||
|
--tw-translate-y: 0;
|
||||||
|
--tw-rotate: 0;
|
||||||
|
--tw-skew-x: 0;
|
||||||
|
--tw-skew-y: 0;
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
--tw-pan-x: ;
|
||||||
|
--tw-pan-y: ;
|
||||||
|
--tw-pinch-zoom: ;
|
||||||
|
--tw-scroll-snap-strictness: proximity;
|
||||||
|
--tw-gradient-from-position: ;
|
||||||
|
--tw-gradient-via-position: ;
|
||||||
|
--tw-gradient-to-position: ;
|
||||||
|
--tw-ordinal: ;
|
||||||
|
--tw-slashed-zero: ;
|
||||||
|
--tw-numeric-figure: ;
|
||||||
|
--tw-numeric-spacing: ;
|
||||||
|
--tw-numeric-fraction: ;
|
||||||
|
--tw-ring-inset: ;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-colored: 0 0 #0000;
|
||||||
|
--tw-blur: ;
|
||||||
|
--tw-brightness: ;
|
||||||
|
--tw-contrast: ;
|
||||||
|
--tw-grayscale: ;
|
||||||
|
--tw-hue-rotate: ;
|
||||||
|
--tw-invert: ;
|
||||||
|
--tw-saturate: ;
|
||||||
|
--tw-sepia: ;
|
||||||
|
--tw-drop-shadow: ;
|
||||||
|
--tw-backdrop-blur: ;
|
||||||
|
--tw-backdrop-brightness: ;
|
||||||
|
--tw-backdrop-contrast: ;
|
||||||
|
--tw-backdrop-grayscale: ;
|
||||||
|
--tw-backdrop-hue-rotate: ;
|
||||||
|
--tw-backdrop-invert: ;
|
||||||
|
--tw-backdrop-opacity: ;
|
||||||
|
--tw-backdrop-saturate: ;
|
||||||
|
--tw-backdrop-sepia: ;
|
||||||
|
--tw-contain-size: ;
|
||||||
|
--tw-contain-layout: ;
|
||||||
|
--tw-contain-paint: ;
|
||||||
|
--tw-contain-style: ;
|
||||||
|
/*border-bottom-width: 1px;*/
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(226 232 240 / var(--tw-border-opacity));
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
.mx-auto {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
.mt-20 {
|
||||||
|
margin-top: 5rem;
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.h-14 {
|
||||||
|
height: 3.5rem;
|
||||||
|
}
|
||||||
|
.h-5 {
|
||||||
|
height: 1.25rem;
|
||||||
|
}
|
||||||
|
.h-6 {
|
||||||
|
height: 1.5rem;
|
||||||
|
}
|
||||||
|
.min-h-full {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
.w-5 {
|
||||||
|
width: 1.25rem;
|
||||||
|
}
|
||||||
|
.w-6 {
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
.w-auto {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
.max-w-7xl {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
.flex-shrink-0 {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.items-start {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.gap-4 {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.gap-8 {
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
.border-b {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
.border-t {
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
.border-slate-100 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(241 245 249 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
.border-slate-200 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(226 232 240 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
.bg-white {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
.p-8 {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
.px-4 {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
.px-40 {
|
||||||
|
padding-left: 10rem;
|
||||||
|
padding-right: 10rem;
|
||||||
|
}
|
||||||
|
.py-10 {
|
||||||
|
padding-top: 2.5rem;
|
||||||
|
padding-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
.text-2xl {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
.text-xs {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
}
|
||||||
|
.text-wrap {
|
||||||
|
max-width: 100%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
.font-bold {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.font-semibold {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.leading-7 {
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
.text-slate-400 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(148 163 184 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
.text-slate-700 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(51 65 85 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
.text-slate-900 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(15 23 42 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
.underline {
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
.opacity-50 {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.opacity-25 {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
.transition {
|
||||||
|
transition-property: color, background-color, border-color,
|
||||||
|
text-decoration-color, fill, stroke, opacity, box-shadow, transform,
|
||||||
|
filter, backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
min-height: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
.hover\:opacity-100:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sm\:-my-px {
|
||||||
|
margin-top: -1px;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
.sm\:ml-6 {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
}
|
||||||
|
.sm\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.sm\:truncate {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.sm\:px-6 {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
.sm\:text-3xl {
|
||||||
|
font-size: 1.875rem;
|
||||||
|
line-height: 2.25rem;
|
||||||
|
}
|
||||||
|
.sm\:tracking-tight {
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.md\:grid {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
.md\:grid-cols-4 {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.md\:gap-4 {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.md\:p-2 {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.lg\:px-8 {
|
||||||
|
padding-left: 2rem;
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="min-h-full">
|
||||||
|
<nav class="border-b border-slate-200 bg-white">
|
||||||
|
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="flex h-14 justify-between">
|
||||||
|
<div class="flex">
|
||||||
|
<div class="flex flex-shrink-0 items-center">
|
||||||
|
<a href="{{ nxCloudUrl }}">
|
||||||
|
<svg
|
||||||
|
id="nx-cloud-header-logo"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="transparent"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="h-6 w-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-1"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-2"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="py-10">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex max-w-7xl flex-col items-start justify-center gap-2 px-40"
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
class="text-2xl leading-7 font-bold text-slate-900 sm:truncate sm:text-3xl sm:tracking-tight"
|
||||||
|
>
|
||||||
|
Your workspace is connected to Nx Cloud
|
||||||
|
</h1>
|
||||||
|
<div>
|
||||||
|
<p class="mb-2">You may now close this window.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer
|
||||||
|
class="mt-20 flex border-t border-slate-100 dark:border-slate-800"
|
||||||
|
>
|
||||||
|
<nav
|
||||||
|
role="menu"
|
||||||
|
aria-labelledby="bottom-navigation"
|
||||||
|
class="mx-auto flex w-auto max-w-7xl items-center px-4 text-slate-400 dark:text-slate-600"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-4 p-8 opacity-50">
|
||||||
|
<a title="Nx Cloud" href="{{ nxCloudUrl }}">
|
||||||
|
<svg
|
||||||
|
id="nx-cloud-header-logo"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="transparent"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="h-5 w-5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-1"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-2"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<p class="text-xs transition">© 2024 - Nx Cloud</p>
|
||||||
|
</div>
|
||||||
|
<section
|
||||||
|
class="hidden gap-8 p-8 text-xs opacity-25 transition hover:opacity-100 md:grid md:grid-cols-4 md:gap-4 md:p-2 lg:flex"
|
||||||
|
>
|
||||||
|
<a href="https://nx.app/terms" title="Terms of Service"
|
||||||
|
>Terms of Service</a
|
||||||
|
><a href="https://nx.app/privacy" title="Privacy Policy"
|
||||||
|
>Privacy Policy</a
|
||||||
|
><a
|
||||||
|
href="https://status.nx.app"
|
||||||
|
title="Status"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>Status</a
|
||||||
|
><a
|
||||||
|
href="https://nx.dev/ci/intro/ci-with-nx?utm_source=nx.app"
|
||||||
|
title="Docs"
|
||||||
|
>Docs</a
|
||||||
|
><a href="mailto:cloud-support@nrwl.io" title="Contact Nx Cloud"
|
||||||
|
>Contact Nx Cloud</a
|
||||||
|
><a href="https://nx.dev/pricing?utm_source=nx.app" title="Pricing"
|
||||||
|
>Pricing</a
|
||||||
|
><a href="https://nx.dev/company?utm_source=nx.app" title="Company"
|
||||||
|
>Company</a
|
||||||
|
><a
|
||||||
|
href="https://twitter.com/nxdevtools"
|
||||||
|
title="@NxDevTools"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>@NxDevTools</a
|
||||||
|
>
|
||||||
|
</section>
|
||||||
|
</nav>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+432
@@ -0,0 +1,432 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Nx Cloud login</title>
|
||||||
|
<style>
|
||||||
|
*,
|
||||||
|
:before,
|
||||||
|
:after {
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
tab-size: 4;
|
||||||
|
font-family:
|
||||||
|
ui-sans-serif,
|
||||||
|
system-ui,
|
||||||
|
sans-serif,
|
||||||
|
'Apple Color Emoji',
|
||||||
|
'Segoe UI Emoji',
|
||||||
|
Segoe UI Symbol,
|
||||||
|
'Noto Color Emoji';
|
||||||
|
font-feature-settings: normal;
|
||||||
|
font-variation-settings: normal;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
line-height: inherit;
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(51 65 85 / var(--tw-text-opacity));
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-width: 0;
|
||||||
|
border-style: solid;
|
||||||
|
--tw-border-spacing-x: 0;
|
||||||
|
--tw-border-spacing-y: 0;
|
||||||
|
--tw-translate-x: 0;
|
||||||
|
--tw-translate-y: 0;
|
||||||
|
--tw-rotate: 0;
|
||||||
|
--tw-skew-x: 0;
|
||||||
|
--tw-skew-y: 0;
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
--tw-pan-x: ;
|
||||||
|
--tw-pan-y: ;
|
||||||
|
--tw-pinch-zoom: ;
|
||||||
|
--tw-scroll-snap-strictness: proximity;
|
||||||
|
--tw-gradient-from-position: ;
|
||||||
|
--tw-gradient-via-position: ;
|
||||||
|
--tw-gradient-to-position: ;
|
||||||
|
--tw-ordinal: ;
|
||||||
|
--tw-slashed-zero: ;
|
||||||
|
--tw-numeric-figure: ;
|
||||||
|
--tw-numeric-spacing: ;
|
||||||
|
--tw-numeric-fraction: ;
|
||||||
|
--tw-ring-inset: ;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-colored: 0 0 #0000;
|
||||||
|
--tw-blur: ;
|
||||||
|
--tw-brightness: ;
|
||||||
|
--tw-contrast: ;
|
||||||
|
--tw-grayscale: ;
|
||||||
|
--tw-hue-rotate: ;
|
||||||
|
--tw-invert: ;
|
||||||
|
--tw-saturate: ;
|
||||||
|
--tw-sepia: ;
|
||||||
|
--tw-drop-shadow: ;
|
||||||
|
--tw-backdrop-blur: ;
|
||||||
|
--tw-backdrop-brightness: ;
|
||||||
|
--tw-backdrop-contrast: ;
|
||||||
|
--tw-backdrop-grayscale: ;
|
||||||
|
--tw-backdrop-hue-rotate: ;
|
||||||
|
--tw-backdrop-invert: ;
|
||||||
|
--tw-backdrop-opacity: ;
|
||||||
|
--tw-backdrop-saturate: ;
|
||||||
|
--tw-backdrop-sepia: ;
|
||||||
|
--tw-contain-size: ;
|
||||||
|
--tw-contain-layout: ;
|
||||||
|
--tw-contain-paint: ;
|
||||||
|
--tw-contain-style: ;
|
||||||
|
/*border-bottom-width: 1px;*/
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(226 232 240 / var(--tw-border-opacity));
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
.mx-auto {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
.mt-20 {
|
||||||
|
margin-top: 5rem;
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.h-14 {
|
||||||
|
height: 3.5rem;
|
||||||
|
}
|
||||||
|
.h-5 {
|
||||||
|
height: 1.25rem;
|
||||||
|
}
|
||||||
|
.h-6 {
|
||||||
|
height: 1.5rem;
|
||||||
|
}
|
||||||
|
.min-h-full {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
.w-5 {
|
||||||
|
width: 1.25rem;
|
||||||
|
}
|
||||||
|
.w-6 {
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
.w-auto {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
.max-w-7xl {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
.flex-shrink-0 {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.items-start {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.gap-4 {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.gap-8 {
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
.border-b {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
.border-t {
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
.border-slate-100 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(241 245 249 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
.border-slate-200 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(226 232 240 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
.bg-white {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
.p-8 {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
.px-4 {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
.px-40 {
|
||||||
|
padding-left: 10rem;
|
||||||
|
padding-right: 10rem;
|
||||||
|
}
|
||||||
|
.py-10 {
|
||||||
|
padding-top: 2.5rem;
|
||||||
|
padding-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
.text-2xl {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
.text-xs {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
}
|
||||||
|
.font-bold {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.font-semibold {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.leading-7 {
|
||||||
|
line-height: 1.75rem;
|
||||||
|
}
|
||||||
|
.text-slate-400 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(148 163 184 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
.text-slate-700 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(51 65 85 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
.text-slate-900 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(15 23 42 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
.underline {
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
.opacity-50 {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.opacity-25 {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
.transition {
|
||||||
|
transition-property: color, background-color, border-color,
|
||||||
|
text-decoration-color, fill, stroke, opacity, box-shadow, transform,
|
||||||
|
filter, backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
min-height: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
.hover\:opacity-100:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sm\:-my-px {
|
||||||
|
margin-top: -1px;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
.sm\:ml-6 {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
}
|
||||||
|
.sm\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.sm\:truncate {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.sm\:px-6 {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
.sm\:text-3xl {
|
||||||
|
font-size: 1.875rem;
|
||||||
|
line-height: 2.25rem;
|
||||||
|
}
|
||||||
|
.sm\:tracking-tight {
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.md\:grid {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
.md\:grid-cols-4 {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
.md\:gap-4 {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.md\:p-2 {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.lg\:px-8 {
|
||||||
|
padding-left: 2rem;
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function startCountdown() {
|
||||||
|
let countdownElement = document.getElementById('countdown');
|
||||||
|
let countdown = 5;
|
||||||
|
|
||||||
|
let interval = setInterval(function () {
|
||||||
|
countdownElement.innerHTML = countdown;
|
||||||
|
countdown--;
|
||||||
|
|
||||||
|
if (countdown < 0) {
|
||||||
|
clearInterval(interval);
|
||||||
|
window.location.href = '{{ redirectUrl }}'; // Replace with your redirect URL
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="startCountdown()">
|
||||||
|
<div class="min-h-full">
|
||||||
|
<nav class="border-b border-slate-200 bg-white">
|
||||||
|
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="flex h-14 justify-between">
|
||||||
|
<div class="flex">
|
||||||
|
<div class="flex flex-shrink-0 items-center">
|
||||||
|
<a href="{{ nxCloudUrl }}">
|
||||||
|
<svg
|
||||||
|
id="nx-cloud-header-logo"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="transparent"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="h-6 w-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-1"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-2"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="py-10">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex max-w-7xl flex-col items-start justify-center gap-2 px-40"
|
||||||
|
>
|
||||||
|
<h1
|
||||||
|
class="text-2xl leading-7 font-bold text-slate-900 sm:truncate sm:text-3xl sm:tracking-tight"
|
||||||
|
>
|
||||||
|
Nx Cloud Login
|
||||||
|
</h1>
|
||||||
|
<div>
|
||||||
|
<p class="mb-2">
|
||||||
|
You will be redirected to
|
||||||
|
<a class="font-semibold underline" href="{{ redirectUrl }}"
|
||||||
|
>Nx Cloud</a
|
||||||
|
>
|
||||||
|
in <span id="countdown">5</span> seconds.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer
|
||||||
|
class="mt-20 flex border-t border-slate-100 dark:border-slate-800"
|
||||||
|
>
|
||||||
|
<nav
|
||||||
|
role="menu"
|
||||||
|
aria-labelledby="bottom-navigation"
|
||||||
|
class="mx-auto flex w-auto max-w-7xl items-center px-4 text-slate-400 dark:text-slate-600"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-4 p-8 opacity-50">
|
||||||
|
<a title="Nx Cloud" href="{{ nxCloudUrl }}">
|
||||||
|
<svg
|
||||||
|
id="nx-cloud-header-logo"
|
||||||
|
role="img"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="transparent"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="h-5 w-5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 3.75V6.5c-3.036 0-5.5 2.464-5.5 5.5s-2.464 5.5-5.5 5.5-5.5 2.464-5.5 5.5H3.75C2.232 23 1 21.768 1 20.25V3.75C1 2.232 2.232 1 3.75 1h16.5C21.768 1 23 2.232 23 3.75Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-1"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
stroke-width="2"
|
||||||
|
d="M23 6v14.1667C23 21.7307 21.7307 23 20.1667 23H6c0-3.128 2.53867-5.6667 5.6667-5.6667 3.128 0 5.6666-2.5386 5.6666-5.6666C17.3333 8.53867 19.872 6 23 6Z"
|
||||||
|
id="nx-cloud-header-logo-stroke-2"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<p class="text-xs transition">© 2024 - Nx Cloud</p>
|
||||||
|
</div>
|
||||||
|
<section
|
||||||
|
class="hidden gap-8 p-8 text-xs opacity-25 transition hover:opacity-100 md:grid md:grid-cols-4 md:gap-4 md:p-2 lg:flex"
|
||||||
|
>
|
||||||
|
<a href="https://nx.app/terms" title="Terms of Service"
|
||||||
|
>Terms of Service</a
|
||||||
|
><a href="https://nx.app/privacy" title="Privacy Policy"
|
||||||
|
>Privacy Policy</a
|
||||||
|
><a
|
||||||
|
href="https://status.nx.app"
|
||||||
|
title="Status"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>Status</a
|
||||||
|
><a
|
||||||
|
href="https://nx.dev/ci/intro/ci-with-nx?utm_source=nx.app"
|
||||||
|
title="Docs"
|
||||||
|
>Docs</a
|
||||||
|
><a href="mailto:cloud-support@nrwl.io" title="Contact Nx Cloud"
|
||||||
|
>Contact Nx Cloud</a
|
||||||
|
><a href="https://nx.dev/pricing?utm_source=nx.app" title="Pricing"
|
||||||
|
>Pricing</a
|
||||||
|
><a href="https://nx.dev/company?utm_source=nx.app" title="Company"
|
||||||
|
>Company</a
|
||||||
|
><a
|
||||||
|
href="https://twitter.com/nxdevtools"
|
||||||
|
title="@NxDevTools"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
>@NxDevTools</a
|
||||||
|
>
|
||||||
|
</section>
|
||||||
|
</nav>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
1760800828171
|
||||||
Vendored
+1874
File diff suppressed because it is too large
Load Diff
Vendored
+652
@@ -0,0 +1,652 @@
|
|||||||
|
{
|
||||||
|
"version": "6.0",
|
||||||
|
"nxVersion": "18.3.5",
|
||||||
|
"deps": {
|
||||||
|
"@changesets/cli": "^2.27.1",
|
||||||
|
"@nx/devkit": "^18.0.0",
|
||||||
|
"@nx/eslint-plugin": "^18.0.0",
|
||||||
|
"@nx/js": "^18.0.0",
|
||||||
|
"@nx/react": "^18.0.0",
|
||||||
|
"@nx/react-native": "^18.0.0",
|
||||||
|
"@nx/workspace": "^18.0.0",
|
||||||
|
"@react-native/eslint-config": "^0.74.0",
|
||||||
|
"@react-native/metro-config": "^0.74.0",
|
||||||
|
"@types/jest": "^29.5.0",
|
||||||
|
"@types/node": "^20.0.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||||
|
"@typescript-eslint/parser": "^6.0.0",
|
||||||
|
"commitlint": "^18.0.0",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
|
"husky": "^8.0.3",
|
||||||
|
"jest": "^29.5.0",
|
||||||
|
"lint-staged": "^15.0.0",
|
||||||
|
"nx": "^18.0.0",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"typescript": "^5.3.0"
|
||||||
|
},
|
||||||
|
"pathMappings": {
|
||||||
|
"@core/security": [
|
||||||
|
"packages/core/security/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/storage": [
|
||||||
|
"packages/core/storage/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/sync": [
|
||||||
|
"packages/core/sync/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/policy-client": [
|
||||||
|
"packages/core/policy-client/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/bff-client": [
|
||||||
|
"packages/core/bff-client/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/runtime": [
|
||||||
|
"packages/core/runtime/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/trust": [
|
||||||
|
"packages/core/trust/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/consent": [
|
||||||
|
"packages/core/consent/src/index.ts"
|
||||||
|
],
|
||||||
|
"@core/analytics": [
|
||||||
|
"packages/core/analytics/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-auth/domain": [
|
||||||
|
"packages/feature-auth/domain/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-auth/data": [
|
||||||
|
"packages/feature-auth/data/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-auth/ui-rn": [
|
||||||
|
"packages/feature-auth/ui-rn/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-tasks/domain": [
|
||||||
|
"packages/feature-tasks/domain/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-tasks/data": [
|
||||||
|
"packages/feature-tasks/data/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-tasks/ui-rn": [
|
||||||
|
"packages/feature-tasks/ui-rn/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-messaging/domain": [
|
||||||
|
"packages/feature-messaging/domain/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-messaging/data": [
|
||||||
|
"packages/feature-messaging/data/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-messaging/ui-rn": [
|
||||||
|
"packages/feature-messaging/ui-rn/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-memberships/domain": [
|
||||||
|
"packages/feature-memberships/domain/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-memberships/data": [
|
||||||
|
"packages/feature-memberships/data/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-memberships/ui-rn": [
|
||||||
|
"packages/feature-memberships/ui-rn/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-media/domain": [
|
||||||
|
"packages/feature-media/domain/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-media/data": [
|
||||||
|
"packages/feature-media/data/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-media/ui-rn": [
|
||||||
|
"packages/feature-media/ui-rn/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-location/domain": [
|
||||||
|
"packages/feature-location/domain/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-location/data": [
|
||||||
|
"packages/feature-location/data/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-location/ui-rn": [
|
||||||
|
"packages/feature-location/ui-rn/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-notes/domain": [
|
||||||
|
"packages/feature-notes/domain/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-notes/data": [
|
||||||
|
"packages/feature-notes/data/src/index.ts"
|
||||||
|
],
|
||||||
|
"@feature-notes/ui-rn": [
|
||||||
|
"packages/feature-notes/ui-rn/src/index.ts"
|
||||||
|
],
|
||||||
|
"@shared/types": [
|
||||||
|
"packages/shared/types/src/index.ts"
|
||||||
|
],
|
||||||
|
"@shared/ui-kit": [
|
||||||
|
"packages/shared/ui-kit/src/index.ts"
|
||||||
|
],
|
||||||
|
"@shared/config": [
|
||||||
|
"packages/shared/config/src/index.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nxJsonPlugins": [],
|
||||||
|
"pluginsConfig": {
|
||||||
|
"@nx/js": {
|
||||||
|
"analyzeSourceFiles": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fileMap": {
|
||||||
|
"nonProjectFiles": [
|
||||||
|
{
|
||||||
|
"file": ".eslintrc.js",
|
||||||
|
"hash": "6372876982733906818"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "best_practices.md",
|
||||||
|
"hash": "13191109570395651909"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "package.json",
|
||||||
|
"hash": "14022645582724659125"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "pnpm-workspace.yaml",
|
||||||
|
"hash": "15678249485940398519"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "nx.json",
|
||||||
|
"hash": "7190034546379248901"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "README.md",
|
||||||
|
"hash": "9564418273127800770"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "commitlint.config.js",
|
||||||
|
"hash": "14643968542317944080"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": ".prettierrc",
|
||||||
|
"hash": "6701623579076507172"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": ".changeset/config.json",
|
||||||
|
"hash": "5450583423988949661"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": ".gitignore",
|
||||||
|
"hash": "13404745306227114823"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": ".lintstagedrc.js",
|
||||||
|
"hash": "9788226683263305028"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "tsconfig.base.json",
|
||||||
|
"hash": "26248645546931930"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "pnpm-lock.yaml",
|
||||||
|
"hash": "6511353211495792909"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/README.playbook.md",
|
||||||
|
"hash": "17685308393363108776"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"projectFileMap": {
|
||||||
|
"@feature/messaging/domain": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-messaging/domain/package.json",
|
||||||
|
"hash": "9875617774836831940"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-messaging/domain/src/index.ts",
|
||||||
|
"hash": "8685286682513873922"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"api-bff": [
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/package.json",
|
||||||
|
"hash": "14667623210490070355"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/config.ts",
|
||||||
|
"hash": "1666143201087972188"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/context.ts",
|
||||||
|
"hash": "3315328324625214844"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/graphql/resolvers.ts",
|
||||||
|
"hash": "16403994371408522013"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/graphql/schema.ts",
|
||||||
|
"hash": "14257578884273712011"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/main.ts",
|
||||||
|
"hash": "14713350618091080358"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/middleware/auth.ts",
|
||||||
|
"hash": "8220961574387728078"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/middleware/dpop.ts",
|
||||||
|
"hash": "4201954442417082965"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/middleware/policy.ts",
|
||||||
|
"hash": "5236659951017462352"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/plugins/rateLimit.ts",
|
||||||
|
"hash": "8945600931265228754"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/plugins/security.ts",
|
||||||
|
"hash": "6908454775761975436"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/shims.d.ts",
|
||||||
|
"hash": "7971519764566029563"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/api-bff/src/utils/logger.ts",
|
||||||
|
"hash": "3008962482417721975"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/tasks/data": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-tasks/data/package.json",
|
||||||
|
"hash": "11899127117492053346"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-tasks/data/src/index.ts",
|
||||||
|
"hash": "3225159343067048056"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/media/domain": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-media/domain/package.json",
|
||||||
|
"hash": "17062343893163365254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-media/domain/src/index.ts",
|
||||||
|
"hash": "11464852676641054833"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sdk-playground": [
|
||||||
|
{
|
||||||
|
"file": "apps/sdk-playground/package.json",
|
||||||
|
"hash": "326704958530458291",
|
||||||
|
"deps": [
|
||||||
|
"@feature/auth/domain",
|
||||||
|
"@feature/auth/data",
|
||||||
|
"@feature/auth/ui-rn",
|
||||||
|
"@feature/tasks/domain",
|
||||||
|
"@feature/tasks/data",
|
||||||
|
"@feature/tasks/ui-rn",
|
||||||
|
"@feature/messaging/domain",
|
||||||
|
"@feature/messaging/data",
|
||||||
|
"@feature/messaging/ui-rn",
|
||||||
|
"@core/security",
|
||||||
|
"@core/storage",
|
||||||
|
"@core/sync",
|
||||||
|
"@core/runtime",
|
||||||
|
"@core/trust",
|
||||||
|
"@core/policy-client",
|
||||||
|
"@shared/ui-kit",
|
||||||
|
"@shared/config"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/trust": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/trust/package.json",
|
||||||
|
"hash": "11344062427660613690"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/trust/src/index.ts",
|
||||||
|
"hash": "4685083431920099583"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/auth/ui-rn": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/ui-rn/package.json",
|
||||||
|
"hash": "10455731927735274696"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/ui-rn/src/index.ts",
|
||||||
|
"hash": "381949698741574035"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/notes/ui-rn": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-notes/ui-rn/package.json",
|
||||||
|
"hash": "3425145873390375585"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-notes/ui-rn/src/index.ts",
|
||||||
|
"hash": "17482866679153039022"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/location/ui-rn": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-location/ui-rn/package.json",
|
||||||
|
"hash": "11710272314659156318"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-location/ui-rn/src/index.ts",
|
||||||
|
"hash": "8200514550807411225"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/messaging/data": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-messaging/data/package.json",
|
||||||
|
"hash": "10890954125212475529"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-messaging/data/src/index.ts",
|
||||||
|
"hash": "11852960011049571049"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/analytics": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/analytics/package.json",
|
||||||
|
"hash": "6997073056337771573"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/analytics/src/index.ts",
|
||||||
|
"hash": "13079790016634135464"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/tasks/domain": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-tasks/domain/package.json",
|
||||||
|
"hash": "7968421340001780022"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-tasks/domain/src/index.ts",
|
||||||
|
"hash": "7513693024026576213"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/storage": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/storage/package.json",
|
||||||
|
"hash": "1852809778144580552",
|
||||||
|
"deps": [
|
||||||
|
"@core/security"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/storage/src/StorageCore.ts",
|
||||||
|
"hash": "7146683357452469950"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/storage/src/index.ts",
|
||||||
|
"hash": "8517838638969559200"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/storage/src/types.ts",
|
||||||
|
"hash": "2812932207384491835"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/location/domain": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-location/domain/package.json",
|
||||||
|
"hash": "15194052582581122561"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-location/domain/src/index.ts",
|
||||||
|
"hash": "3235115917934848004"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/notes/domain": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-notes/domain/package.json",
|
||||||
|
"hash": "2781267393011564746"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-notes/domain/src/index.ts",
|
||||||
|
"hash": "15540426896796287860"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@shared/ui-kit": [
|
||||||
|
{
|
||||||
|
"file": "packages/shared/ui-kit/package.json",
|
||||||
|
"hash": "361889283475743605"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/shared/ui-kit/src/index.ts",
|
||||||
|
"hash": "1495522589135463161"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/security": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/security/package.json",
|
||||||
|
"hash": "8924048311028988599"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/security/src/DPoPService.ts",
|
||||||
|
"hash": "10390908045962685343"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/security/src/SecurityCore.ts",
|
||||||
|
"hash": "3826594692922136891"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/security/src/index.ts",
|
||||||
|
"hash": "596490254292345753"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/security/src/types.ts",
|
||||||
|
"hash": "8154128090190173393"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/memberships/ui-rn": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-memberships/ui-rn/package.json",
|
||||||
|
"hash": "3464485720477174187"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-memberships/ui-rn/src/index.ts",
|
||||||
|
"hash": "10244998141591208299"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@shared/types": [
|
||||||
|
{
|
||||||
|
"file": "packages/shared/types/package.json",
|
||||||
|
"hash": "14468150301333608260"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/shared/types/src/index.ts",
|
||||||
|
"hash": "5454463154077490740"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/sync": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/sync/package.json",
|
||||||
|
"hash": "16260031721964662842"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/sync/src/index.ts",
|
||||||
|
"hash": "17988048760711089847"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/auth/data": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/data/package.json",
|
||||||
|
"hash": "10771143471172556269"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/data/src/index.ts",
|
||||||
|
"hash": "10995026970057222994"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lynkedup-pro": [
|
||||||
|
{
|
||||||
|
"file": "apps/lynkedup-pro/App.tsx",
|
||||||
|
"hash": "9844630877106829463"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/lynkedup-pro/package.json",
|
||||||
|
"hash": "13599407938796017664",
|
||||||
|
"deps": [
|
||||||
|
"@feature/auth/ui-rn",
|
||||||
|
"@feature/tasks/ui-rn",
|
||||||
|
"@feature/messaging/ui-rn",
|
||||||
|
"@feature/memberships/ui-rn",
|
||||||
|
"@feature/media/ui-rn",
|
||||||
|
"@feature/location/ui-rn",
|
||||||
|
"@feature/notes/ui-rn",
|
||||||
|
"@core/security",
|
||||||
|
"@core/storage",
|
||||||
|
"@core/sync",
|
||||||
|
"@core/runtime",
|
||||||
|
"@core/trust",
|
||||||
|
"@shared/ui-kit",
|
||||||
|
"@shared/config"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/consent": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/consent/package.json",
|
||||||
|
"hash": "2406702405332497792"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/consent/src/index.ts",
|
||||||
|
"hash": "15398399444077924226"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/bff-client": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/bff-client/package.json",
|
||||||
|
"hash": "14191312059114809810"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/bff-client/src/index.ts",
|
||||||
|
"hash": "1963496366619874069"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/runtime": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/runtime/package.json",
|
||||||
|
"hash": "12029274047704042540"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/runtime/src/index.ts",
|
||||||
|
"hash": "13435449207607865068"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/auth/domain": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/package.json",
|
||||||
|
"hash": "17800333722898260269"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/src/entities.ts",
|
||||||
|
"hash": "628376922343113656"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/src/index.ts",
|
||||||
|
"hash": "16373159067630076710"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/src/interfaces.ts",
|
||||||
|
"hash": "15907178123305760911"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/src/usecases/BiometricUseCase.ts",
|
||||||
|
"hash": "16600743426124629929"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/src/usecases/LoginUseCase.ts",
|
||||||
|
"hash": "1002106219325659606"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/src/usecases/RegistrationUseCase.ts",
|
||||||
|
"hash": "5953517819967016616"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-auth/domain/src/usecases/SessionUseCase.ts",
|
||||||
|
"hash": "15614570693026768161"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lynkedup-foundation": [
|
||||||
|
{
|
||||||
|
"file": "apps/lynkedup-foundation/App.tsx",
|
||||||
|
"hash": "17713191757927086337"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "apps/lynkedup-foundation/package.json",
|
||||||
|
"hash": "14324450803089748865",
|
||||||
|
"deps": [
|
||||||
|
"@core/security",
|
||||||
|
"@core/storage"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@core/policy-client": [
|
||||||
|
{
|
||||||
|
"file": "packages/core/policy-client/package.json",
|
||||||
|
"hash": "10097230252047303042"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/core/policy-client/src/index.ts",
|
||||||
|
"hash": "7263863394109193832"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/messaging/ui-rn": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-messaging/ui-rn/package.json",
|
||||||
|
"hash": "17304427166648939030"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-messaging/ui-rn/src/index.ts",
|
||||||
|
"hash": "3944964343452623300"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/tasks/ui-rn": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-tasks/ui-rn/package.json",
|
||||||
|
"hash": "13268231782288366417"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-tasks/ui-rn/src/index.ts",
|
||||||
|
"hash": "13401205232392578550"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/memberships/domain": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-memberships/domain/package.json",
|
||||||
|
"hash": "2043205501934190150"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-memberships/domain/src/index.ts",
|
||||||
|
"hash": "16892346130382263542"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@feature/media/ui-rn": [
|
||||||
|
{
|
||||||
|
"file": "packages/feature-media/ui-rn/package.json",
|
||||||
|
"hash": "16525178962787410060"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/feature-media/ui-rn/src/index.ts",
|
||||||
|
"hash": "3244589877537068955"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@shared/config": [
|
||||||
|
{
|
||||||
|
"file": "packages/shared/config/package.json",
|
||||||
|
"hash": "13578451786421307272"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "packages/shared/config/src/index.ts",
|
||||||
|
"hash": "5914740374241226574"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
6256108439935025365
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
+19085
File diff suppressed because it is too large
Load Diff
Vendored
+20249
File diff suppressed because it is too large
Load Diff
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"run": {
|
||||||
|
"command": "nx test",
|
||||||
|
"startTime": "2025-10-18T15:21:14.003Z",
|
||||||
|
"endTime": "2025-10-18T15:23:23.778Z",
|
||||||
|
"inner": false
|
||||||
|
},
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"taskId": "@core/security:test",
|
||||||
|
"target": "test",
|
||||||
|
"projectName": "@core/security",
|
||||||
|
"hash": "1225338222049529083",
|
||||||
|
"startTime": "2025-10-18T15:21:14.023Z",
|
||||||
|
"endTime": "2025-10-18T15:23:23.776Z",
|
||||||
|
"params": "",
|
||||||
|
"cacheStatus": "cache-miss",
|
||||||
|
"status": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+387
@@ -0,0 +1,387 @@
|
|||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
|
||||||
|
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
|
||||||
|
(node:20288) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:19756) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:2060) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:22064) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:2760) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:22576) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:23904) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:6360) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:24972) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:18144) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:22380) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:26016) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:27040) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:10432) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:28300) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:24616) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:28972) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/security:test
|
||||||
|
(node:29648) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/security@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
'nx' is not recognized as an internal or external command,
|
||||||
|
operable program or batch file.
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/security failed[39m
|
||||||
|
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
|
||||||
|
[2m-[22m @core/security:test
|
||||||
|
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
|
||||||
|
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error workspace @core/security@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\security
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
+332
@@ -0,0 +1,332 @@
|
|||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
|
||||||
|
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
|
||||||
|
(node:11848) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:15860) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:16268) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:16760) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:18132) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:18608) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:19152) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:20196) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:9396) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:20860) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:22016) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:13124) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:22572) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:23832) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:24356) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:24900) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:17772) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:22000) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:25924) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:26972) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:27504) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:28264) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:25212) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @feature/auth/domain:test
|
||||||
|
(node:28936) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @feature/auth/domain@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
'nx' is not recognized as an internal or external command,
|
||||||
|
operable program or batch file.
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @feature/auth/domain failed[39m
|
||||||
|
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
|
||||||
|
[2m-[22m @feature/auth/domain:test
|
||||||
|
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
|
||||||
|
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
|
||||||
+347
@@ -0,0 +1,347 @@
|
|||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
|
||||||
|
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
|
||||||
|
(node:17196) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:22152) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:22424) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:22784) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:23976) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:23584) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:25040) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:17124) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:25652) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:26012) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:27108) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:26728) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:28392) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:21808) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:29388) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
[2m> [22m[2mnx run[22m @core/storage:test
|
||||||
|
(node:29336) [DEP0060] DeprecationWarning: The `util._extend` API is deprecated. Please use Object.assign() instead.
|
||||||
|
(Use `node --trace-deprecation ...` to show where the warning was created)
|
||||||
|
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
|
||||||
|
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
|
||||||
|
> @core/storage@1.0.0 test
|
||||||
|
> nx test
|
||||||
|
'nx' is not recognized as an internal or external command,
|
||||||
|
operable program or batch file.
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[0m[7m[1m[31m NX [39m[22m[27m[0m [31mRunning target test for project @core/storage failed[39m
|
||||||
|
|
||||||
|
[2mFailed tasks:[22m
|
||||||
|
|
||||||
|
[2m-[22m @core/storage:test
|
||||||
|
|
||||||
|
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
|
||||||
|
|
||||||
|
|
||||||
|
[0m[7m[1m[33m NX [39m[22m[27m[0m [33mNx Cloud encountered some problems[39m
|
||||||
|
|
||||||
|
Invalid Credentials (CI Access Token): A workspace could not be found with the provided CI Access Token. (code: 401)
|
||||||
|
|
||||||
|
npm error Lifecycle script `test` failed with error:
|
||||||
|
npm error code 1
|
||||||
|
npm error path D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error workspace @core/storage@1.0.0
|
||||||
|
npm error location D:\lynkedup-monorepo\packages\core\storage
|
||||||
|
npm error command failed
|
||||||
|
npm error command C:\Windows\system32\cmd.exe /d /s /c nx test
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 100,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"bracketSameLine": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
# LynkedUp Platform
|
||||||
|
|
||||||
|
> Mobile-first SDK-based application suite with enterprise-grade security and offline-first capabilities
|
||||||
|
|
||||||
|
[](https://github.com/lynkedup/monorepo/actions)
|
||||||
|
[](LICENSE)
|
||||||
|
|
||||||
|
## 🏗️ Architecture Overview
|
||||||
|
|
||||||
|
LynkedUp is built as a **PNPM monorepo** with **Nx orchestration**, featuring:
|
||||||
|
|
||||||
|
- **📱 Mobile-First**: React Native applications with native security integrations
|
||||||
|
- **🔐 Security by Default**: Hardware-backed cryptography, DPoP, SQLCipher encryption
|
||||||
|
- **📴 Offline-First**: 100% functional offline with conflict-free synchronization
|
||||||
|
- **🎯 SDK-First Modularity**: Independent, composable SDKs with strict boundaries
|
||||||
|
- **🛡️ Policy-Aware**: Fine-grained ABAC via Permit.io/OPA
|
||||||
|
- **🏢 Multi-Tenant**: Organization-level encryption keys and data isolation
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A[LynkedUp Pro App] --> B[Feature SDKs]
|
||||||
|
A --> C[Core SDKs]
|
||||||
|
D[LynkedUp Foundation] --> B
|
||||||
|
D --> C
|
||||||
|
|
||||||
|
B --> E[@feature/auth<br/>@feature/tasks<br/>@feature/messaging]
|
||||||
|
C --> F[@core/security<br/>@core/storage<br/>@core/sync<br/>@core/policy]
|
||||||
|
|
||||||
|
F --> G[Native Layer<br/>SQLCipher • Secure Enclave • StrongBox]
|
||||||
|
C --> H[GraphQL BFF<br/>Node.js • Permit.io • PostgreSQL]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Node.js 18+
|
||||||
|
- PNPM 8+
|
||||||
|
- React Native development environment
|
||||||
|
- Xcode (iOS) / Android Studio (Android)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone and install dependencies
|
||||||
|
git clone https://github.com/lynkedup/monorepo.git
|
||||||
|
cd lynkedup-monorepo
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# Initialize development environment
|
||||||
|
pnpm nx run-many -t build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start SDK playground for development
|
||||||
|
pnpm dev:playground
|
||||||
|
|
||||||
|
# Start LynkedUp Pro app
|
||||||
|
pnpm dev:pro
|
||||||
|
|
||||||
|
# Run tests across all packages
|
||||||
|
pnpm test
|
||||||
|
|
||||||
|
# Run only affected tests (recommended)
|
||||||
|
pnpm affected:test
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Package Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
lynkedup-monorepo/
|
||||||
|
├── apps/
|
||||||
|
│ ├── lynkedup-pro/ # Primary React Native app
|
||||||
|
│ ├── lynkedup-foundation/ # Foundation variant
|
||||||
|
│ ├── api-bff/ # Node.js GraphQL BFF
|
||||||
|
│ └── sdk-playground/ # SDK development sandbox
|
||||||
|
├── packages/
|
||||||
|
│ ├── core/ # Tier 0: Infrastructure SDKs
|
||||||
|
│ │ ├── security/ # Hardware-backed crypto, DPoP
|
||||||
|
│ │ ├── storage/ # Encrypted RxDB/SQLCipher
|
||||||
|
│ │ ├── sync/ # Offline-first synchronization
|
||||||
|
│ │ ├── policy-client/ # ABAC policy evaluation
|
||||||
|
│ │ └── trust/ # Device posture & risk assessment
|
||||||
|
│ ├── feature-auth/ # Tier 1: Authentication
|
||||||
|
│ │ ├── domain/ # Pure business logic
|
||||||
|
│ │ ├── data/ # Repository implementations
|
||||||
|
│ │ └── ui-rn/ # React Native components
|
||||||
|
│ ├── feature-tasks/ # Task & project management
|
||||||
|
│ ├── feature-messaging/ # Unified messaging backbone
|
||||||
|
│ └── shared/ # Common utilities & types
|
||||||
|
└── tooling/ # Development tools & mocks
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 Security Features
|
||||||
|
|
||||||
|
- **Hardware-Backed Keys**: iOS Secure Enclave & Android StrongBox
|
||||||
|
- **DPoP Authentication**: RFC 9449 sender-constrained tokens
|
||||||
|
- **Contextual Encryption**: Organization-specific data encryption keys
|
||||||
|
- **Cryptographic Erasure**: Remote data destruction via key deletion
|
||||||
|
- **Device Attestation**: Apple DeviceCheck & Play Integrity integration
|
||||||
|
- **Policy-Driven Access**: Real-time ABAC enforcement
|
||||||
|
|
||||||
|
## 📴 Offline Capabilities
|
||||||
|
|
||||||
|
- **Local-First Storage**: Encrypted SQLCipher with reactive queries
|
||||||
|
- **Durable Outbox Pattern**: Reliable offline mutation queuing
|
||||||
|
- **CRDT Synchronization**: Conflict-free collaborative data
|
||||||
|
- **Optimistic UI**: Immediate feedback with eventual consistency
|
||||||
|
- **Policy Caching**: Local ABAC evaluation with server enforcement
|
||||||
|
|
||||||
|
## 🛠️ Development Workflow
|
||||||
|
|
||||||
|
### Module Boundaries
|
||||||
|
|
||||||
|
The monorepo enforces strict architectural boundaries via ESLint rules:
|
||||||
|
|
||||||
|
- **Domain Purity**: Domain layers cannot import infrastructure
|
||||||
|
- **Vertical Isolation**: Features cannot depend on other features
|
||||||
|
- **Layered Dependencies**: UI → Data → Domain → Shared
|
||||||
|
|
||||||
|
### SDK Development
|
||||||
|
|
||||||
|
Each SDK follows clean architecture principles:
|
||||||
|
|
||||||
|
1. **Domain Layer**: Pure TypeScript business logic
|
||||||
|
2. **Data Layer**: Infrastructure adapters (RxDB, GraphQL, native modules)
|
||||||
|
3. **UI Layer**: React Native components and screens
|
||||||
|
|
||||||
|
See individual SDK playbooks in `packages/*/README.playbook.md`.
|
||||||
|
|
||||||
|
### Testing Strategy
|
||||||
|
|
||||||
|
- **Unit Tests**: High coverage for business logic (Jest)
|
||||||
|
- **Contract Tests**: GraphQL schema compliance (MSW)
|
||||||
|
- **Integration Tests**: Cross-SDK interactions
|
||||||
|
- **E2E Tests**: Complete user flows (Detox)
|
||||||
|
|
||||||
|
## 📋 Available Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Development
|
||||||
|
pnpm dev:playground # SDK development sandbox
|
||||||
|
pnpm dev:pro # LynkedUp Pro app
|
||||||
|
pnpm dev:foundation # LynkedUp Foundation app
|
||||||
|
|
||||||
|
# Quality Assurance
|
||||||
|
pnpm build # Build all packages
|
||||||
|
pnpm test # Run all tests
|
||||||
|
pnpm lint # Lint all packages
|
||||||
|
pnpm typecheck # TypeScript validation
|
||||||
|
|
||||||
|
# Affected Operations (CI/CD)
|
||||||
|
pnpm affected:build # Build affected packages
|
||||||
|
pnpm affected:test # Test affected packages
|
||||||
|
pnpm affected:lint # Lint affected packages
|
||||||
|
|
||||||
|
# Release Management
|
||||||
|
pnpm changeset # Create changeset
|
||||||
|
pnpm changeset:version # Bump versions
|
||||||
|
pnpm changeset:publish # Publish to NPM
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚢 Release Management
|
||||||
|
|
||||||
|
This monorepo uses [Changesets](https://github.com/changesets/changesets) for versioning and publishing:
|
||||||
|
|
||||||
|
1. **Create Changeset**: `pnpm changeset`
|
||||||
|
2. **Version Bump**: `pnpm changeset:version`
|
||||||
|
3. **Publish**: `pnpm changeset:publish`
|
||||||
|
|
||||||
|
Only SDK packages are published to NPM. Applications are deployment artifacts.
|
||||||
|
|
||||||
|
## 🧪 CI/CD Pipeline
|
||||||
|
|
||||||
|
- **SLSA Level 3**: Supply chain security with signed provenance
|
||||||
|
- **Nx Cloud**: Remote caching for optimal build performance
|
||||||
|
- **Affected Testing**: Only test/build changed packages
|
||||||
|
- **Semantic Versioning**: Automated version management
|
||||||
|
- **Security Scanning**: Dependency and code vulnerability checks
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
- **Architecture**: [docs/architecture.md](docs/architecture.md)
|
||||||
|
- **Security Model**: [docs/security.md](docs/security.md)
|
||||||
|
- **SDK Playbooks**: `packages/*/README.playbook.md`
|
||||||
|
- **API Reference**: Generated from TypeScript types
|
||||||
|
- **GraphQL Schema**: `apps/api-bff/schema.graphql`
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
1. **Create Feature Branch**: `git checkout -b feat/scope-description`
|
||||||
|
2. **Follow Conventions**: Conventional Commits with proper scopes
|
||||||
|
3. **Add Changeset**: `pnpm changeset` for public API changes
|
||||||
|
4. **Quality Gates**: Pre-commit hooks ensure code quality
|
||||||
|
5. **Pull Request**: Title should match commit convention
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
Copyright (c) 2024 LynkedUp Platform. All rights reserved.
|
||||||
|
|
||||||
|
This software is proprietary and confidential. Unauthorized copying, distribution, or use is strictly prohibited.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"name": "api-bff",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "LynkedUp GraphQL Backend for Frontend (BFF)",
|
||||||
|
"license": "ISC",
|
||||||
|
"author": "",
|
||||||
|
"type": "module",
|
||||||
|
"main": "src/main.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"start": "node src/main.ts",
|
||||||
|
"dev": "tsx watch src/main.ts",
|
||||||
|
"test": "jest",
|
||||||
|
"lint": "eslint src --ext .ts",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"codegen": "graphql-codegen --config codegen.ts",
|
||||||
|
"db:migrate": "prisma migrate dev",
|
||||||
|
"db:generate": "prisma generate",
|
||||||
|
"db:seed": "tsx src/database/seed.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@apollo/server": "^4.9.5",
|
||||||
|
"@as-integrations/fastify": "^2.1.1",
|
||||||
|
"@fastify/cors": "^8.4.0",
|
||||||
|
"@fastify/helmet": "^11.1.1",
|
||||||
|
"@fastify/rate-limit": "^9.0.1",
|
||||||
|
"@graphql-tools/schema": "^10.0.0",
|
||||||
|
"@open-policy-agent/opa": "^2.0.0",
|
||||||
|
"@prisma/client": "^5.6.0",
|
||||||
|
"@types/express": "^5.0.6",
|
||||||
|
"axios": "^1.13.2",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"dataloader": "^2.2.2",
|
||||||
|
"express": "^5.2.1",
|
||||||
|
"fastify": "^4.24.3",
|
||||||
|
"graphql": "^16.8.1",
|
||||||
|
"graphql-scalars": "^1.22.4",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"pino": "^8.17.0",
|
||||||
|
"redis": "^4.6.10",
|
||||||
|
"uuid": "^9.0.1",
|
||||||
|
"zod": "^3.22.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@graphql-codegen/cli": "^5.0.0",
|
||||||
|
"@graphql-codegen/typescript": "^4.0.1",
|
||||||
|
"@graphql-codegen/typescript-resolvers": "^4.0.1",
|
||||||
|
"@types/bcrypt": "^5.0.2",
|
||||||
|
"@types/jsonwebtoken": "^9.0.5",
|
||||||
|
"@types/node": "^20.9.0",
|
||||||
|
"@types/uuid": "^9.0.7",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||||
|
"@typescript-eslint/parser": "^6.12.0",
|
||||||
|
"eslint": "^8.54.0",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"prisma": "^5.6.0",
|
||||||
|
"ts-jest": "^29.1.1",
|
||||||
|
"tsx": "^4.4.0",
|
||||||
|
"typescript": "^5.2.2"
|
||||||
|
},
|
||||||
|
"nx": {
|
||||||
|
"tags": [
|
||||||
|
"scope:app",
|
||||||
|
"type:api",
|
||||||
|
"platform:node"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export const config = {
|
||||||
|
env: (process && process.env && process.env.NODE_ENV) || 'development',
|
||||||
|
port: Number(process?.env?.PORT) || 4000,
|
||||||
|
host: process?.env?.HOST || '0.0.0.0',
|
||||||
|
version: '0.0.0',
|
||||||
|
cors: { allowedOrigins: ['*'] },
|
||||||
|
permitio: { pdpUrl: process?.env?.PERMIT_PDP_URL || '', apiKey: process?.env?.PERMIT_API_KEY || '' }
|
||||||
|
};
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export type Context = any;
|
||||||
|
|
||||||
|
export function createContext({ request, reply }: { request?: any; reply?: any }): Context {
|
||||||
|
return { request, reply } as Context;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export const resolvers = {
|
||||||
|
Query: {
|
||||||
|
_empty: () => 'ok'
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export const typeDefs = `
|
||||||
|
type Query { _empty: String }
|
||||||
|
`;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import express from "express";
|
||||||
|
import projectsRouter from "./routes/projects";
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
app.use("/api", projectsRouter);
|
||||||
|
|
||||||
|
app.listen(3000, () => console.log("Server running on http://localhost:3000"));
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export const authMiddleware = async (request: any, reply: any) => {
|
||||||
|
// stub: authenticate request and attach `user` to request in real implementation
|
||||||
|
request.user = request.user || { sub: 'anonymous' };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default authMiddleware;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export const dpopMiddleware = async (request: any, reply: any) => {
|
||||||
|
// stub: validate DPoP headers in real implementation
|
||||||
|
};
|
||||||
|
|
||||||
|
export default dpopMiddleware;
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export const policyMiddleware = async (request: any, reply: any) => {
|
||||||
|
// stub: evaluate ABAC policies; attach decisions to request
|
||||||
|
request.policy = { allowed: true };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default policyMiddleware;
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { Request, Response, NextFunction } from "express";
|
||||||
|
import { checkAccess } from "../services/authz";
|
||||||
|
|
||||||
|
type CrudAction = "create" | "read" | "update" | "delete" | "admin" | "view";
|
||||||
|
|
||||||
|
function isNonEmptyString(v: unknown): v is string {
|
||||||
|
return typeof v === "string" && v.trim().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function requireAccess(
|
||||||
|
getConfig: (req: Request) => {
|
||||||
|
userId: string;
|
||||||
|
resourceName: string;
|
||||||
|
action: CrudAction;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
return async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const cfg = getConfig(req);
|
||||||
|
|
||||||
|
const userId = cfg?.userId;
|
||||||
|
const resourceName = cfg?.resourceName;
|
||||||
|
const action = cfg?.action;
|
||||||
|
|
||||||
|
// ✅ Validate early (prevents calling OPA with undefined/null)
|
||||||
|
if (!isNonEmptyString(userId) || !isNonEmptyString(resourceName) || !isNonEmptyString(action)) {
|
||||||
|
return res.status(400).json({
|
||||||
|
message: "Missing or invalid authorization inputs",
|
||||||
|
details: {
|
||||||
|
userId: userId ?? null,
|
||||||
|
resourceName: resourceName ?? null,
|
||||||
|
action: action ?? null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("AUTHZ INPUT:", { userId, resourceName, action });
|
||||||
|
|
||||||
|
// checkAccess MUST build:
|
||||||
|
// { input: { user: {id:userId}, resource:{name:resourceName}, action } }
|
||||||
|
const allowed = await checkAccess({ userId, resourceName, action });
|
||||||
|
|
||||||
|
console.log("AUTHZ RESULT:", allowed);
|
||||||
|
|
||||||
|
if (!allowed) {
|
||||||
|
return res.status(403).json({ message: "Forbidden: access denied" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
} catch (e: any) {
|
||||||
|
return res.status(502).json({
|
||||||
|
message: "Authorization service error",
|
||||||
|
error: e?.message ?? "Unknown error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export const rateLimitPlugin = async (server: any, opts: any) => {
|
||||||
|
// stub: register rate limiting hooks
|
||||||
|
};
|
||||||
|
|
||||||
|
export default rateLimitPlugin;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export const securityPlugin = async (server: any, opts: any) => {
|
||||||
|
// stub: set security-related Fastify hooks
|
||||||
|
};
|
||||||
|
|
||||||
|
export default securityPlugin;
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { Router } from "express";
|
||||||
|
import { requireAccess } from "../middleware/requireAccess";
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
// CREATE (uses payload values)
|
||||||
|
router.post(
|
||||||
|
"/projects",
|
||||||
|
requireAccess((req) => ({
|
||||||
|
userId: req.body.userId,
|
||||||
|
resourceName: req.body.resourceName,
|
||||||
|
action: req.body.action,
|
||||||
|
})),
|
||||||
|
async (req, res) => {
|
||||||
|
res.json({ message: "Project created" });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// READ (if you still want body-based auth)
|
||||||
|
router.get(
|
||||||
|
"/projects/:name",
|
||||||
|
requireAccess((req) => ({
|
||||||
|
userId: req.body.userId,
|
||||||
|
resourceName: req.body.resourceName ?? req.params.name,
|
||||||
|
action: req.body.action ?? "read",
|
||||||
|
})),
|
||||||
|
async (req, res) => {
|
||||||
|
res.json({ name: req.params.name });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// UPDATE (body-based)
|
||||||
|
router.put(
|
||||||
|
"/projects/:name",
|
||||||
|
requireAccess((req) => ({
|
||||||
|
userId: req.body.userId,
|
||||||
|
resourceName: req.body.resourceName ?? req.params.name,
|
||||||
|
action: req.body.action ?? "update",
|
||||||
|
})),
|
||||||
|
async (req, res) => {
|
||||||
|
res.json({ message: "Project updated" });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// DELETE (body-based)
|
||||||
|
router.delete(
|
||||||
|
"/projects/:name",
|
||||||
|
requireAccess((req) => ({
|
||||||
|
userId: req.body.userId,
|
||||||
|
resourceName: req.body.resourceName ?? req.params.name,
|
||||||
|
action: req.body.action ?? "delete",
|
||||||
|
})),
|
||||||
|
async (req, res) => {
|
||||||
|
res.json({ message: "Project deleted" });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { opaAllow } from "./opaClient";
|
||||||
|
|
||||||
|
export async function checkAccess(params: {
|
||||||
|
userId: string;
|
||||||
|
resourceName: string;
|
||||||
|
action: string;
|
||||||
|
}): Promise<boolean> {
|
||||||
|
return opaAllow({
|
||||||
|
input: {
|
||||||
|
user: { id: params.userId },
|
||||||
|
resource: { name: params.resourceName },
|
||||||
|
action: params.action,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import { AccessRequest, AccessResponse } from "../types/authz";
|
||||||
|
|
||||||
|
const OPA_URL = "http://64.227.108.180:8182/v1/data/authz/access/allow";
|
||||||
|
|
||||||
|
export async function opaAllow(payload: AccessRequest): Promise<boolean> {
|
||||||
|
console.log("OPA REQUEST:", JSON.stringify(payload, null, 2));
|
||||||
|
|
||||||
|
const res = await axios.post<AccessResponse>(OPA_URL, payload, {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
timeout: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("OPA RESPONSE:", JSON.stringify(res.data, null, 2));
|
||||||
|
return Boolean(res.data?.result);
|
||||||
|
}
|
||||||
Vendored
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/* Minimal external module shims for static analysis. Keep these permissive. */
|
||||||
|
|
||||||
|
declare module 'fastify' {
|
||||||
|
const Fastify: any;
|
||||||
|
export type FastifyInstance = any;
|
||||||
|
export default Fastify;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@apollo/server' {
|
||||||
|
export class ApolloServer<T = any> {
|
||||||
|
constructor(options?: any);
|
||||||
|
start?(): Promise<void>;
|
||||||
|
stop?(): Promise<void>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@as-integrations/fastify' {
|
||||||
|
const fastifyApollo: any;
|
||||||
|
export default fastifyApollo;
|
||||||
|
export const fastifyApolloDrainPlugin: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@apollo/server-plugin-landing-page-local-default' {
|
||||||
|
export const ApolloServerPluginLandingPageLocalDefault: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@graphql-tools/schema' {
|
||||||
|
export function makeExecutableSchema(...args: any[]): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@permitio/permit-node' {
|
||||||
|
export class Permit { constructor(opts?: any); check(...args: any[]): Promise<any>; }
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@fastify/cors';
|
||||||
|
declare module '@fastify/helmet';
|
||||||
|
|
||||||
|
declare var process: any;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package permission
|
||||||
|
|
||||||
|
import data.role_permissions
|
||||||
|
|
||||||
|
default allow := false
|
||||||
|
|
||||||
|
allow if {
|
||||||
|
some role in input.subject.roles
|
||||||
|
some permission in role_permissions[role]
|
||||||
|
permission.action == input.action
|
||||||
|
permission.object == input.object
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"subject": {
|
||||||
|
"roles": [
|
||||||
|
"admin"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export interface AccessRequest {
|
||||||
|
input: {
|
||||||
|
user: { id: string };
|
||||||
|
resource: { name: string };
|
||||||
|
action: string; // "admin" | "view" | "read" | "create" | etc.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccessResponse {
|
||||||
|
result: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const logger = console;
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
# 📘 Project Best Practices
|
||||||
|
|
||||||
|
## 1. Project Purpose
|
||||||
|
LynkedUp is a mobile-first, SDK-driven application suite with enterprise-grade security and offline-first capabilities. It is structured as a PNPM monorepo orchestrated by Nx, providing modular Core SDKs (security, storage, sync, policy, trust) and Feature SDKs (auth, tasks, messaging, etc.) consumed by React Native apps and a Node.js GraphQL BFF.
|
||||||
|
|
||||||
|
## 2. Project Structure
|
||||||
|
- Monorepo
|
||||||
|
- apps/
|
||||||
|
- lynkedup-pro/ and lynkedup-foundation/: React Native apps demonstrating SDK composition.
|
||||||
|
- api-bff/: Node.js Fastify + Apollo GraphQL Backend For Frontend.
|
||||||
|
- sdk-playground/: Development sandbox for SDKs.
|
||||||
|
- packages/
|
||||||
|
- core/: Tier-0 infrastructure SDKs (e.g., security, storage, sync, policy-client, runtime, trust).# 📘 Project Best Practices
|
||||||
|
|
||||||
|
## 1. Project Purpose
|
||||||
|
LynkedUp is a mobile-first, SDK-driven application suite with enterprise-grade security and offline-first capabilities. It is structured as a PNPM monorepo orchestrated by Nx, providing modular Core SDKs (security, storage, sync, policy, trust) and Feature SDKs (auth, tasks, messaging, etc.) consumed by React Native apps and a Node.js GraphQL BFF.
|
||||||
|
|
||||||
|
## 2. Project Structure
|
||||||
|
- Monorepo
|
||||||
|
- apps/
|
||||||
|
- lynkedup-pro/ and lynkedup-foundation/: React Native apps demonstrating SDK composition.
|
||||||
|
- api-bff/: Node.js Fastify + Apollo GraphQL Backend For Frontend.
|
||||||
|
- sdk-playground/: Development sandbox for SDKs.
|
||||||
|
- packages/
|
||||||
|
- core/: Tier-0 infrastructure SDKs (e.g., security, storage, sync, policy-client, runtime, trust).
|
||||||
|
- feature-*/: Tier-1 feature SDKs following clean architecture (domain, data, ui-rn).
|
||||||
|
- shared/: Common types, config, and UI kit.
|
||||||
|
- Tooling & Config: Nx, ESLint, Prettier, Changesets, Commitlint.
|
||||||
|
|
||||||
|
- Separation of concerns (Clean Architecture conventions)
|
||||||
|
- Feature SDKs:
|
||||||
|
- domain/: Pure business logic (use cases, entities, interfaces). No platform or infra dependencies.
|
||||||
|
- data/: Repositories/adapters that implement domain interfaces and talk to core SDKs and BFF.
|
||||||
|
- ui-rn/: React Native components and navigation.
|
||||||
|
- Core SDKs provide foundational services (e.g., SecurityCore, StorageCore) that feature data layers depend on.
|
||||||
|
- Apps initialize and compose SDKs; they own configuration and feature toggles.
|
||||||
|
|
||||||
|
- Entry points & configuration
|
||||||
|
- apps/api-bff/src/main.ts: Fastify server + Apollo schema wiring and middleware registration.
|
||||||
|
- apps/*/App.tsx: SDK initialization sequence (Security → Storage → Sync → Runtime → Trust) and navigation bootstrapping.
|
||||||
|
- packages/*/src/index.ts: Barrel files re-exporting public API for each package.
|
||||||
|
- tsconfig.base.json: Strict TypeScript with path aliases for all packages.
|
||||||
|
|
||||||
|
## 3. Test Strategy
|
||||||
|
- Framework: Jest (Nx managed). Use per-package unit tests with co-located *.spec.ts(x) files.
|
||||||
|
- Suggested organization (based on architecture):
|
||||||
|
- Domain layer: Unit tests for use cases (pure, no I/O). Mock via interfaces.
|
||||||
|
- Data layer: Contract tests for GraphQL and network using MSW; integration tests with core SDKs.
|
||||||
|
- Core SDKs: Unit tests for deterministic logic; integration tests for cross-SDK interactions.
|
||||||
|
- Apps: E2E tests with Detox for key flows.
|
||||||
|
- Mocking guidelines:
|
||||||
|
- Mock via domain interfaces (e.g., IAuthRepository, ITrustRepository) rather than concrete classes.
|
||||||
|
- For GraphQL, prefer MSW to mock network boundaries rather than stubbing internals.
|
||||||
|
- Use dependency injection to pass fakes/mocks into use cases.
|
||||||
|
- Coverage expectations:
|
||||||
|
- Aim high on domain logic (>90%).
|
||||||
|
- Maintain pragmatic coverage for data/adapters; prefer integration and contract tests.
|
||||||
|
- CI:
|
||||||
|
- Use nx affected:test for efficient runs.
|
||||||
|
|
||||||
|
## 4. Code Style
|
||||||
|
- Languages & typing
|
||||||
|
- TypeScript with strict mode enabled. Prefer precise types and interfaces over any.
|
||||||
|
- Public APIs should have explicit return types (ESLint warns on missing types).
|
||||||
|
- Favor async/await over promise chains; avoid top-level side effects.
|
||||||
|
- Naming conventions
|
||||||
|
- Classes: PascalCase (e.g., SecurityCore, LoginUseCase).
|
||||||
|
- Functions/variables: camelCase.
|
||||||
|
- Files: index.ts as package barrels; core classes often use PascalCase file names (e.g., SecurityCore.ts). Keep barrels aligned with actual exports.
|
||||||
|
- Packages follow scopes (@core/*, @feature-*/domain|data|ui-rn, @shared/*).
|
||||||
|
- Formatting
|
||||||
|
- Prettier: singleQuote, semi, printWidth 100, arrowParens avoid, LF line endings.
|
||||||
|
- Enforced via lint-staged on staged files.
|
||||||
|
- Lint rules & boundaries
|
||||||
|
- ESLint: no-unused-vars (ignore args prefixed with _), explicit-function-return-type warn.
|
||||||
|
- Module boundaries via @nx/enforce-module-boundaries with tags:
|
||||||
|
- type:domain → only depend on [type:domain, type:types, scope:shared].
|
||||||
|
- type:data → depend on [type:domain, type:types, scope:core, scope:shared].
|
||||||
|
- type:ui → depend on [type:data, type:domain, type:types, scope:shared].
|
||||||
|
- scope:feature cannot depend on other scope:feature.
|
||||||
|
- scope:core only depends on [scope:core, scope:shared, type:types].
|
||||||
|
- platform:shared cannot depend on platform:rn or platform:node.
|
||||||
|
- Ensure each Nx library is properly tagged to satisfy these constraints.
|
||||||
|
- Documentation & comments
|
||||||
|
- Use concise JSDoc for public APIs and to mark FRD references (e.g., F.SC.004).
|
||||||
|
- Map errors to user-friendly codes/messages at boundaries (see LoginUseCase.handleLoginError).
|
||||||
|
- Error handling
|
||||||
|
- Guard methods with ensureInitialized() where applicable (e.g., SecurityCore, StorageCore).
|
||||||
|
- On server, do not expose internals in production (see BFF formatError).
|
||||||
|
|
||||||
|
## 5. Common Patterns
|
||||||
|
- Clean Architecture layering (UI → Data → Domain → Shared Types) and dependency inversion via interfaces.
|
||||||
|
- SDK initialization order in apps: Security → Storage → Sync → Runtime → Trust → Feature SDKs.
|
||||||
|
- Barrel exports (index.ts) per package for a stable public surface.
|
||||||
|
- GraphQL BFF:
|
||||||
|
- Fastify plugins for security (helmet, cors) and custom plugins (security, rateLimit).
|
||||||
|
- Middleware order: DPoP → Auth → Policy (ABAC) before GraphQL handler.
|
||||||
|
- Dynamic imports for optional dependencies (e.g., Permit.io client).
|
||||||
|
- Security & cryptography
|
||||||
|
- Hardware-backed keys, DPoP proof generation, envelope encryption with organizational DEKs.
|
||||||
|
- Cryptographic erasure and secure wipe via key management.
|
||||||
|
- Offline-first storage
|
||||||
|
- Encrypted local DB, schema registry, selective purge by organization, re-keying (planned).
|
||||||
|
|
||||||
|
## 6. Do's and Don'ts
|
||||||
|
- Do
|
||||||
|
- Initialize core SDKs in the documented order before feature initialization.
|
||||||
|
- Keep domain logic pure and free from platform or network code.
|
||||||
|
- Depend on interfaces in domain; implement in data with adapters to core SDKs/BFF.
|
||||||
|
- Use path aliases from tsconfig.base.json; export public API via index.ts.
|
||||||
|
- Respect ESLint module boundaries and Nx tags; add proper library tags when creating new packages.
|
||||||
|
- Map server errors to safe messages in production; log full details server-side only.
|
||||||
|
- Use MSW for network contract tests; keep unit tests fast and deterministic.
|
||||||
|
- Follow Conventional Commits with configured scopes and the additional `security` type.
|
||||||
|
- Keep barrel files accurate and synchronized with actual implementation files.
|
||||||
|
- Don't
|
||||||
|
- Import across features (no feature-to-feature dependencies).
|
||||||
|
- Make domain depend on data/core/platform code.
|
||||||
|
- Bypass ensureInitialized guards in core SDKs.
|
||||||
|
- Expose stack traces or sensitive details to clients in production.
|
||||||
|
- Hardcode secrets or environment-specific values; use config and env vars.
|
||||||
|
- Introduce Node-specific APIs into React Native code paths.
|
||||||
|
|
||||||
|
## 7. Tools & Dependencies
|
||||||
|
- Tooling
|
||||||
|
- PNPM workspaces + Nx orchestration (caching, affected commands).
|
||||||
|
- ESLint + Prettier + lint-staged; commitlint with conventional commits.
|
||||||
|
- Changesets for versioning and publishing (SDK packages only).
|
||||||
|
- Key libraries
|
||||||
|
- Apps: React Native, React Navigation.
|
||||||
|
- BFF: Fastify, @apollo/server, @graphql-tools/schema, @fastify/cors, @fastify/helmet, optional Permit.io.
|
||||||
|
- Core SDKs: Security (DPoP, key management, encryption), Storage (encrypted DB, schema registry), Sync/Runtime/Trust (per architecture).
|
||||||
|
- Setup
|
||||||
|
- Install: pnpm install; build: pnpm nx run-many -t build.
|
||||||
|
- Dev scripts: dev:playground, dev:pro, dev:foundation.
|
||||||
|
- Tests: pnpm test or pnpm affected:test.
|
||||||
|
- BFF env vars: NODE_ENV, PORT (default 4000), HOST (default 0.0.0.0), PERMIT_PDP_URL, PERMIT_API_KEY.
|
||||||
|
|
||||||
|
- Separation of concerns (Clean Architecture conventions)
|
||||||
|
- Feature SDKs:
|
||||||
|
- domain/: Pure business logic (use cases, entities, interfaces). No platform or infra dependencies.
|
||||||
|
- data/: Repositories/adapters that implement domain interfaces and talk to core SDKs and BFF.
|
||||||
|
- ui-rn/: React Native components and navigation.
|
||||||
|
- Core SDKs provide foundational services (e.g., SecurityCore, StorageCore) that feature data layers depend on.
|
||||||
|
- Apps initialize and compose SDKs; they own configuration and feature toggles.
|
||||||
|
|
||||||
|
- Entry points & configuration
|
||||||
|
- apps/api-bff/src/main.ts: Fastify server + Apollo schema wiring and middleware registration.
|
||||||
|
- apps/*/App.tsx: SDK initialization sequence (Security → Storage → Sync → Runtime → Trust) and navigation bootstrapping.
|
||||||
|
- packages/*/src/index.ts: Barrel files re-exporting public API for each package.
|
||||||
|
- tsconfig.base.json: Strict TypeScript with path aliases for all packages.
|
||||||
|
|
||||||
|
## 3. Test Strategy
|
||||||
|
- Framework: Jest (Nx managed). Use per-package unit tests with co-located *.spec.ts(x) files.
|
||||||
|
- Suggested organization (based on architecture):
|
||||||
|
- Domain layer: Unit tests for use cases (pure, no I/O). Mock via interfaces.
|
||||||
|
- Data layer: Contract tests for GraphQL and network using MSW; integration tests with core SDKs.
|
||||||
|
- Core SDKs: Unit tests for deterministic logic; integration tests for cross-SDK interactions.
|
||||||
|
- Apps: E2E tests with Detox for key flows.
|
||||||
|
- Mocking guidelines:
|
||||||
|
- Mock via domain interfaces (e.g., IAuthRepository, ITrustRepository) rather than concrete classes.
|
||||||
|
- For GraphQL, prefer MSW to mock network boundaries rather than stubbing internals.
|
||||||
|
- Use dependency injection to pass fakes/mocks into use cases.
|
||||||
|
- Coverage expectations:
|
||||||
|
- Aim high on domain logic (>90%).
|
||||||
|
- Maintain pragmatic coverage for data/adapters; prefer integration and contract tests.
|
||||||
|
- CI:
|
||||||
|
- Use nx affected:test for efficient runs.
|
||||||
|
|
||||||
|
## 4. Code Style
|
||||||
|
- Languages & typing
|
||||||
|
- TypeScript with strict mode enabled. Prefer precise types and interfaces over any.
|
||||||
|
- Public APIs should have explicit return types (ESLint warns on missing types).
|
||||||
|
- Favor async/await over promise chains; avoid top-level side effects.
|
||||||
|
- Naming conventions
|
||||||
|
- Classes: PascalCase (e.g., SecurityCore, LoginUseCase).
|
||||||
|
- Functions/variables: camelCase.
|
||||||
|
- Files: index.ts as package barrels; core classes often use PascalCase file names (e.g., SecurityCore.ts). Keep barrels aligned with actual exports.
|
||||||
|
- Packages follow scopes (@core/*, @feature-*/domain|data|ui-rn, @shared/*).
|
||||||
|
- Formatting
|
||||||
|
- Prettier: singleQuote, semi, printWidth 100, arrowParens avoid, LF line endings.
|
||||||
|
- Enforced via lint-staged on staged files.
|
||||||
|
- Lint rules & boundaries
|
||||||
|
- ESLint: no-unused-vars (ignore args prefixed with _), explicit-function-return-type warn.
|
||||||
|
- Module boundaries via @nx/enforce-module-boundaries with tags:
|
||||||
|
- type:domain → only depend on [type:domain, type:types, scope:shared].
|
||||||
|
- type:data → depend on [type:domain, type:types, scope:core, scope:shared].
|
||||||
|
- type:ui → depend on [type:data, type:domain, type:types, scope:shared].
|
||||||
|
- scope:feature cannot depend on other scope:feature.
|
||||||
|
- scope:core only depends on [scope:core, scope:shared, type:types].
|
||||||
|
- platform:shared cannot depend on platform:rn or platform:node.
|
||||||
|
- Ensure each Nx library is properly tagged to satisfy these constraints.
|
||||||
|
- Documentation & comments
|
||||||
|
- Use concise JSDoc for public APIs and to mark FRD references (e.g., F.SC.004).
|
||||||
|
- Map errors to user-friendly codes/messages at boundaries (see LoginUseCase.handleLoginError).
|
||||||
|
- Error handling
|
||||||
|
- Guard methods with ensureInitialized() where applicable (e.g., SecurityCore, StorageCore).
|
||||||
|
- On server, do not expose internals in production (see BFF formatError).
|
||||||
|
|
||||||
|
## 5. Common Patterns
|
||||||
|
- Clean Architecture layering (UI → Data → Domain → Shared Types) and dependency inversion via interfaces.
|
||||||
|
- SDK initialization order in apps: Security → Storage → Sync → Runtime → Trust → Feature SDKs.
|
||||||
|
- Barrel exports (index.ts) per package for a stable public surface.
|
||||||
|
- GraphQL BFF:
|
||||||
|
- Fastify plugins for security (helmet, cors) and custom plugins (security, rateLimit).
|
||||||
|
- Middleware order: DPoP → Auth → Policy (ABAC) before GraphQL handler.
|
||||||
|
- Dynamic imports for optional dependencies (e.g., Permit.io client).
|
||||||
|
- Security & cryptography
|
||||||
|
- Hardware-backed keys, DPoP proof generation, envelope encryption with organizational DEKs.
|
||||||
|
- Cryptographic erasure and secure wipe via key management.
|
||||||
|
- Offline-first storage
|
||||||
|
- Encrypted local DB, schema registry, selective purge by organization, re-keying (planned).
|
||||||
|
|
||||||
|
## 6. Do's and Don'ts
|
||||||
|
- Do
|
||||||
|
- Initialize core SDKs in the documented order before feature initialization.
|
||||||
|
- Keep domain logic pure and free from platform or network code.
|
||||||
|
- Depend on interfaces in domain; implement in data with adapters to core SDKs/BFF.
|
||||||
|
- Use path aliases from tsconfig.base.json; export public API via index.ts.
|
||||||
|
- Respect ESLint module boundaries and Nx tags; add proper library tags when creating new packages.
|
||||||
|
- Map server errors to safe messages in production; log full details server-side only.
|
||||||
|
- Use MSW for network contract tests; keep unit tests fast and deterministic.
|
||||||
|
- Follow Conventional Commits with configured scopes and the additional `security` type.
|
||||||
|
- Keep barrel files accurate and synchronized with actual implementation files.
|
||||||
|
- Don't
|
||||||
|
- Import across features (no feature-to-feature dependencies).
|
||||||
|
- Make domain depend on data/core/platform code.
|
||||||
|
- Bypass ensureInitialized guards in core SDKs.
|
||||||
|
- Expose stack traces or sensitive details to clients in production.
|
||||||
|
- Hardcode secrets or environment-specific values; use config and env vars.
|
||||||
|
- Introduce Node-specific APIs into React Native code paths.
|
||||||
|
|
||||||
|
## 7. Tools & Dependencies
|
||||||
|
- Tooling
|
||||||
|
- PNPM workspaces + Nx orchestration (caching, affected commands).
|
||||||
|
- ESLint + Prettier + lint-staged; commitlint with conventional commits.
|
||||||
|
- Changesets for versioning and publishing (SDK packages only).
|
||||||
|
- Key libraries
|
||||||
|
- Apps: React Native, React Navigation.
|
||||||
|
- BFF: Fastify, @apollo/server, @graphql-tools/schema, @fastify/cors, @fastify/helmet, optional Permit.io.
|
||||||
|
- Core SDKs: Security (DPoP, key management, encryption), Storage (encrypted DB, schema registry), Sync/Runtime/Trust (per architecture).
|
||||||
|
- Setup
|
||||||
|
- Install: pnpm install; build: pnpm nx run-many -t build.
|
||||||
|
- Dev scripts: dev:playground, dev:pro, dev:foundation.
|
||||||
|
- Tests: pnpm test or pnpm affected:test.
|
||||||
|
- BFF env vars: NODE_ENV, PORT (default 4000), HOST (default 0.0.0.0), PERMIT_PDP_URL, PERMIT_API_KEY.
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['@commitlint/config-conventional'],
|
||||||
|
rules: {
|
||||||
|
'type-enum': [
|
||||||
|
2,
|
||||||
|
'always',
|
||||||
|
[
|
||||||
|
'build',
|
||||||
|
'chore',
|
||||||
|
'ci',
|
||||||
|
'docs',
|
||||||
|
'feat',
|
||||||
|
'fix',
|
||||||
|
'perf',
|
||||||
|
'refactor',
|
||||||
|
'revert',
|
||||||
|
'style',
|
||||||
|
'test',
|
||||||
|
'security' // Added for security-related changes
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'scope-enum': [
|
||||||
|
2,
|
||||||
|
'always',
|
||||||
|
[
|
||||||
|
// Core SDKs
|
||||||
|
'security',
|
||||||
|
'storage',
|
||||||
|
'sync',
|
||||||
|
'policy',
|
||||||
|
'bff-client',
|
||||||
|
'runtime',
|
||||||
|
'trust',
|
||||||
|
'consent',
|
||||||
|
'analytics',
|
||||||
|
|
||||||
|
// Feature SDKs
|
||||||
|
'auth',
|
||||||
|
'tasks',
|
||||||
|
'messaging',
|
||||||
|
'memberships',
|
||||||
|
'media',
|
||||||
|
'location',
|
||||||
|
'notes',
|
||||||
|
|
||||||
|
// Apps
|
||||||
|
'pro-app',
|
||||||
|
'foundation-app',
|
||||||
|
'playground',
|
||||||
|
|
||||||
|
// Infrastructure
|
||||||
|
'monorepo',
|
||||||
|
'ci',
|
||||||
|
'deps',
|
||||||
|
'release'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'subject-case': [2, 'never', ['pascal-case', 'upper-case']],
|
||||||
|
'subject-max-length': [2, 'always', 72]
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
||||||
|
"extends": "nx/presets/npm.json",
|
||||||
|
"tasksRunnerOptions": {
|
||||||
|
"default": {
|
||||||
|
"runner": "nx-cloud",
|
||||||
|
"options": {
|
||||||
|
"cacheableOperations": ["build", "test", "lint", "typecheck"],
|
||||||
|
"accessToken": "process.env.NX_CLOUD_ACCESS_TOKEN"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetDefaults": {
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": ["^build"],
|
||||||
|
"inputs": ["production", "^production"]
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"]
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"cache": true,
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"{workspaceRoot}/.eslintrc.js",
|
||||||
|
"{workspaceRoot}/.eslintignore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"typecheck": {
|
||||||
|
"cache": true,
|
||||||
|
"inputs": ["default", "^production"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"namedInputs": {
|
||||||
|
"default": ["{projectRoot}/**/*", "sharedGlobals"],
|
||||||
|
"production": [
|
||||||
|
"default",
|
||||||
|
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
|
||||||
|
"!{projectRoot}/tsconfig.spec.json",
|
||||||
|
"!{projectRoot}/jest.config.[jt]s",
|
||||||
|
"!{projectRoot}/src/test-setup.[jt]s",
|
||||||
|
"!{projectRoot}/test-setup.[jt]s",
|
||||||
|
"!{projectRoot}/.eslintrc.json",
|
||||||
|
"!{projectRoot}/eslint.config.js"
|
||||||
|
],
|
||||||
|
"sharedGlobals": []
|
||||||
|
},
|
||||||
|
"generators": {
|
||||||
|
"@nx/react": {
|
||||||
|
"application": {
|
||||||
|
"babel": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@nx/react-native": {
|
||||||
|
"application": {
|
||||||
|
"unitTestRunner": "jest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"projects": ["packages/**"],
|
||||||
|
"changelog": {
|
||||||
|
"workspaceChangelog": false,
|
||||||
|
"projectChangelogs": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "lynkedup-monorepo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "LynkedUp Platform - Mobile-first SDK-based application suite",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nx run-many -t build",
|
||||||
|
"test": "nx run-many -t test",
|
||||||
|
"lint": "nx run-many -t lint",
|
||||||
|
"typecheck": "nx run-many -t typecheck",
|
||||||
|
"affected:build": "nx affected -t build",
|
||||||
|
"affected:test": "nx affected -t test",
|
||||||
|
"affected:lint": "nx affected -t lint",
|
||||||
|
"changeset": "changeset",
|
||||||
|
"changeset:version": "changeset version",
|
||||||
|
"changeset:publish": "changeset publish",
|
||||||
|
"dev:playground": "nx serve sdk-playground",
|
||||||
|
"dev:pro": "nx start lynkedup-pro",
|
||||||
|
"dev:foundation": "nx start lynkedup-foundation"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@changesets/cli": "^2.27.1",
|
||||||
|
"@nx/devkit": "^18.0.0",
|
||||||
|
"@nx/eslint-plugin": "^18.0.0",
|
||||||
|
"@nx/js": "^18.0.0",
|
||||||
|
"@nx/react": "^18.0.0",
|
||||||
|
"@nx/react-native": "^18.0.0",
|
||||||
|
"@nx/workspace": "^18.0.0",
|
||||||
|
"@react-native/eslint-config": "^0.74.0",
|
||||||
|
"@react-native/metro-config": "^0.74.0",
|
||||||
|
"@types/jest": "^29.5.0",
|
||||||
|
"@types/node": "^20.0.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||||
|
"@typescript-eslint/parser": "^6.0.0",
|
||||||
|
"commitlint": "^18.0.0",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
|
"husky": "^8.0.3",
|
||||||
|
"jest": "^29.5.0",
|
||||||
|
"lint-staged": "^15.0.0",
|
||||||
|
"nx": "^18.0.0",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"typescript": "^5.3.0"
|
||||||
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"apps/*",
|
||||||
|
"packages/core/*",
|
||||||
|
"packages/feature-*",
|
||||||
|
"packages/shared/*",
|
||||||
|
"tooling/*"
|
||||||
|
],
|
||||||
|
"packageManager": "pnpm@10.18.3+sha512.bbd16e6d7286fd7e01f6b3c0b3c932cda2965c06a908328f74663f10a9aea51f1129eea615134bf992831b009eabe167ecb7008b597f40ff9bc75946aadfb08d"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/analytics",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"nx": { "tags": ["scope:core","type:infra"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const AnalyticsCore = {};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/bff-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"nx": { "tags": ["scope:core","type:infra"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const BFFClient = {};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/consent",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"nx": { "tags": ["scope:core","type:infra"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const ConsentCore = {};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/policy-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"nx": { "tags": ["scope:core","type:infra"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const PolicyClient = {};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/runtime",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"nx": { "tags": ["scope:core","type:infra"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const RuntimeCore = {};
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/security",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Core security SDK for hardware-backed cryptography, DPoP, and contextual encryption",
|
||||||
|
"main": "./src/index.ts",
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nx build",
|
||||||
|
"test": "nx test",
|
||||||
|
"lint": "nx lint",
|
||||||
|
"typecheck": "nx typecheck"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react-native-keychain": "^8.2.0",
|
||||||
|
"react-native-crypto-js": "^1.0.0",
|
||||||
|
"uuid": "^9.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/uuid": "^9.0.7"
|
||||||
|
},
|
||||||
|
"nx": {
|
||||||
|
"tags": ["scope:core", "type:infra", "platform:rn"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import type { DPoPProof } from './types';
|
||||||
|
|
||||||
|
// Note: This requires a custom Native Module (NativeCryptoModule) capable of
|
||||||
|
// generating ECC keys in the Secure Enclave and signing data with them.
|
||||||
|
// This is a placeholder implementation that would need native module integration.
|
||||||
|
|
||||||
|
const DPOP_KEY_ALIAS = 'lynkedup.dpop.key.v1';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DPoP (Demonstrating Proof-of-Possession) Service
|
||||||
|
* Implements RFC 9449 for sender-constrained access tokens
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Hardware-backed ECC key generation
|
||||||
|
* - JWT signing with private key in secure enclave
|
||||||
|
* - Request binding via HTTP method and URI
|
||||||
|
*/
|
||||||
|
export class DPoPService {
|
||||||
|
private publicKey: string | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize DPoP key pair in secure enclave
|
||||||
|
* Returns the public key JWK
|
||||||
|
*/
|
||||||
|
async initializeKeyPair(): Promise<string> {
|
||||||
|
if (this.publicKey) return this.publicKey;
|
||||||
|
|
||||||
|
// Check if key exists natively using the alias, otherwise generate it
|
||||||
|
// This would call into a native module
|
||||||
|
let pubKey = await this.getPublicKeyFromNative(DPOP_KEY_ALIAS);
|
||||||
|
|
||||||
|
if (!pubKey) {
|
||||||
|
pubKey = await this.generateHardwareECCKeyPair(DPOP_KEY_ALIAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.publicKey = pubKey;
|
||||||
|
return pubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign a DPoP proof for HTTP request
|
||||||
|
* @param method HTTP method (GET, POST, etc.)
|
||||||
|
* @param uri Full request URI
|
||||||
|
* @param accessToken Optional access token to bind to request
|
||||||
|
*/
|
||||||
|
async signProof(method: string, uri: string, accessToken?: string): Promise<string> {
|
||||||
|
if (!this.publicKey) {
|
||||||
|
await this.initializeKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the DPoP JWT payload (htu, htm, jti, ath)
|
||||||
|
const payload = {
|
||||||
|
htm: method, // HTTP Method
|
||||||
|
htu: uri, // HTTP URI
|
||||||
|
jti: uuidv4(), // Unique identifier for this proof
|
||||||
|
iat: Math.floor(Date.now() / 1000), // Issued at time
|
||||||
|
// Include hash of access token (ath) if present
|
||||||
|
ath: accessToken ? this.base64url(this.sha256(accessToken)) : undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sign the JWT using the hardware-backed private key via the native module
|
||||||
|
const signedJwt = await this.signJWTWithNative(payload, DPOP_KEY_ALIAS);
|
||||||
|
|
||||||
|
return signedJwt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign arbitrary data with DPoP key
|
||||||
|
*/
|
||||||
|
async signData(data: string): Promise<string> {
|
||||||
|
if (!this.publicKey) {
|
||||||
|
await this.initializeKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
const signaturePayload = {
|
||||||
|
data,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
nonce: uuidv4()
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.signJWTWithNative(signaturePayload, DPOP_KEY_ALIAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current public key
|
||||||
|
*/
|
||||||
|
getPublicKey(): string | null {
|
||||||
|
return this.publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Native module integration methods (would be implemented via bridge)
|
||||||
|
private async getPublicKeyFromNative(keyAlias: string): Promise<string | null> {
|
||||||
|
// This would call into a native module
|
||||||
|
// Example: return NativeCryptoModule.getPublicKey(keyAlias);
|
||||||
|
console.warn('Native module integration required for getPublicKeyFromNative');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async generateHardwareECCKeyPair(keyAlias: string): Promise<string> {
|
||||||
|
// This would call into a native module to generate ECC key in secure enclave
|
||||||
|
// Example: return NativeCryptoModule.generateHardwareECCKeyPair(keyAlias);
|
||||||
|
console.warn('Native module integration required for generateHardwareECCKeyPair');
|
||||||
|
|
||||||
|
// Mock implementation for development
|
||||||
|
return JSON.stringify({
|
||||||
|
kty: 'EC',
|
||||||
|
crv: 'P-256',
|
||||||
|
x: 'mock-x-coordinate',
|
||||||
|
y: 'mock-y-coordinate',
|
||||||
|
use: 'sig',
|
||||||
|
kid: keyAlias
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async signJWTWithNative(payload: any, keyAlias: string): Promise<string> {
|
||||||
|
// This would call into a native module to sign JWT with hardware key
|
||||||
|
// Example: return NativeCryptoModule.signJWT(payload, keyAlias);
|
||||||
|
console.warn('Native module integration required for signJWTWithNative');
|
||||||
|
|
||||||
|
// Mock implementation for development
|
||||||
|
const header = { alg: 'ES256', typ: 'dpop+jwt', jwk: JSON.parse(this.publicKey!) };
|
||||||
|
const encodedHeader = this.base64url(JSON.stringify(header));
|
||||||
|
const encodedPayload = this.base64url(JSON.stringify(payload));
|
||||||
|
const signature = 'mock-signature'; // Would be actual signature from secure enclave
|
||||||
|
|
||||||
|
return `${encodedHeader}.${encodedPayload}.${signature}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility methods
|
||||||
|
private base64url(str: string): string {
|
||||||
|
return Buffer.from(str)
|
||||||
|
.toString('base64')
|
||||||
|
.replace(/\+/g, '-')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/=/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
private sha256(str: string): string {
|
||||||
|
// This would use a proper crypto library
|
||||||
|
console.warn('Proper SHA256 implementation required');
|
||||||
|
return 'mock-hash';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
import { DPoPService } from './DPoPService';
|
||||||
|
import { CryptoService } from './CryptoService';
|
||||||
|
import { KeyManagementService } from './KeyManagementService';
|
||||||
|
import type { SecurityConfig, EncryptionResult, KeyReference } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Security SDK
|
||||||
|
* Provides hardware-backed cryptography, DPoP implementation, and contextual encryption
|
||||||
|
*
|
||||||
|
* Key Features (per FRD):
|
||||||
|
* - F.SC.001: Cryptographic utilities (AES-GCM envelope encryption)
|
||||||
|
* - F.SC.002: Hardware-backed key storage (Keychain/StrongBox)
|
||||||
|
* - F.SC.003: Certificate Pinning logic
|
||||||
|
* - F.SC.004: DPoP proof generation
|
||||||
|
* - F.SC.005: Organizational Data Encryption Keys (DEKs) management
|
||||||
|
* - F.SC.006: Secure wipe/cryptographic erasure
|
||||||
|
* - F.SC.007: Device attestation integration
|
||||||
|
*/
|
||||||
|
export class SecurityCore {
|
||||||
|
private config: SecurityConfig;
|
||||||
|
private dpopService: DPoPService;
|
||||||
|
private cryptoService: CryptoService;
|
||||||
|
private keyManagement: KeyManagementService;
|
||||||
|
private initialized = false;
|
||||||
|
|
||||||
|
constructor(config: SecurityConfig) {
|
||||||
|
this.config = config;
|
||||||
|
this.dpopService = new DPoPService();
|
||||||
|
this.cryptoService = new CryptoService();
|
||||||
|
this.keyManagement = new KeyManagementService(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the Security Core
|
||||||
|
* Must be called before any other operations
|
||||||
|
*/
|
||||||
|
async initialize(): Promise<void> {
|
||||||
|
if (this.initialized) return;
|
||||||
|
|
||||||
|
await this.keyManagement.initialize();
|
||||||
|
await this.dpopService.initializeKeyPair();
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.SC.004: Generate DPoP proof for request authentication
|
||||||
|
*/
|
||||||
|
async signDPoPProof(method: string, uri: string, accessToken?: string): Promise<string> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
return this.dpopService.signProof(method, uri, accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.SC.001: Encrypt data using organizational DEK (envelope encryption)
|
||||||
|
*/
|
||||||
|
async encryptForOrganization(data: string, orgId: string): Promise<EncryptionResult> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
// Get or create organizational DEK
|
||||||
|
const orgKeyRef = await this.keyManagement.getOrganizationalKey(orgId);
|
||||||
|
|
||||||
|
// Generate random file encryption key
|
||||||
|
const fileKey = await this.cryptoService.generateKey();
|
||||||
|
|
||||||
|
// Encrypt data with file key
|
||||||
|
const encryptedData = await this.cryptoService.encrypt(data, fileKey);
|
||||||
|
|
||||||
|
// Wrap file key with organizational DEK
|
||||||
|
const wrappedKey = await this.cryptoService.wrapKey(fileKey, orgKeyRef.keyId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
encryptedData: encryptedData.ciphertext,
|
||||||
|
keyReference: {
|
||||||
|
keyId: wrappedKey,
|
||||||
|
orgId,
|
||||||
|
keyType: 'dek',
|
||||||
|
createdAt: new Date().toISOString()
|
||||||
|
},
|
||||||
|
iv: encryptedData.iv,
|
||||||
|
authTag: encryptedData.authTag
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt data using organizational DEK
|
||||||
|
*/
|
||||||
|
async decryptForOrganization(encryptedData: string, keyReference: KeyReference): Promise<string> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
if (!keyReference.orgId) {
|
||||||
|
throw new Error('Organization ID required for decryption');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get organizational DEK
|
||||||
|
const orgKeyRef = await this.keyManagement.getOrganizationalKey(keyReference.orgId);
|
||||||
|
|
||||||
|
// Unwrap file key
|
||||||
|
const fileKey = await this.cryptoService.unwrapKey(keyReference.keyId, orgKeyRef.keyId);
|
||||||
|
|
||||||
|
// Decrypt data
|
||||||
|
return this.cryptoService.decrypt(encryptedData, fileKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.SC.002: Get database master key from secure storage
|
||||||
|
*/
|
||||||
|
async getDatabaseMasterKey(): Promise<string> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
return this.keyManagement.getDatabaseMasterKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.SC.005: Store authentication tokens securely
|
||||||
|
*/
|
||||||
|
async storeAuthTokens(accessToken: string, refreshToken: string): Promise<void> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
await this.keyManagement.storeSecureValue('auth.access_token', accessToken);
|
||||||
|
await this.keyManagement.storeSecureValue('auth.refresh_token', refreshToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get stored authentication tokens
|
||||||
|
*/
|
||||||
|
async getAuthTokens(): Promise<{ accessToken?: string; refreshToken?: string }> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
const [accessToken, refreshToken] = await Promise.all([
|
||||||
|
this.keyManagement.getSecureValue('auth.access_token'),
|
||||||
|
this.keyManagement.getSecureValue('auth.refresh_token')
|
||||||
|
]);
|
||||||
|
|
||||||
|
return { accessToken, refreshToken };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.SC.006: Cryptographic erasure - delete organizational keys
|
||||||
|
*/
|
||||||
|
async performCryptographicErasure(orgId: string): Promise<void> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
await this.keyManagement.deleteOrganizationalKeys(orgId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.SC.006: Complete secure wipe - delete all keys
|
||||||
|
*/
|
||||||
|
async performSecureWipe(): Promise<void> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
await this.keyManagement.secureWipe();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign arbitrary data with identity key
|
||||||
|
*/
|
||||||
|
async signData(data: string): Promise<string> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
return this.dpopService.signData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ensureInitialized(): void {
|
||||||
|
if (!this.initialized) {
|
||||||
|
throw new Error('SecurityCore must be initialized before use');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export { SecurityCore } from './SecurityCore';
|
||||||
|
export { DPoPService } from './DPoPService';
|
||||||
|
export { CryptoService } from './CryptoService';
|
||||||
|
export { KeyManagementService } from './KeyManagementService';
|
||||||
|
export type {
|
||||||
|
SecurityConfig,
|
||||||
|
DPoPProof,
|
||||||
|
EncryptionResult,
|
||||||
|
KeyReference,
|
||||||
|
SecurityLevel
|
||||||
|
} from './types';
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
export interface SecurityConfig {
|
||||||
|
enableHardwareBackedStorage: boolean;
|
||||||
|
requireSecureEnclave: boolean;
|
||||||
|
enableCertificatePinning: boolean;
|
||||||
|
allowDebugging: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DPoPProof {
|
||||||
|
jwt: string;
|
||||||
|
publicKey: string;
|
||||||
|
algorithm: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EncryptionResult {
|
||||||
|
encryptedData: string;
|
||||||
|
keyReference: KeyReference;
|
||||||
|
iv: string;
|
||||||
|
authTag: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KeyReference {
|
||||||
|
keyId: string;
|
||||||
|
orgId?: string;
|
||||||
|
keyType: 'master' | 'dek' | 'dpop' | 'identity';
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SecurityLevel {
|
||||||
|
SOFTWARE = 'software',
|
||||||
|
SECURE_HARDWARE = 'secure_hardware',
|
||||||
|
SECURE_ENCLAVE = 'secure_enclave'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AttestationResult {
|
||||||
|
status: 'VALID' | 'INVALID' | 'UNKNOWN';
|
||||||
|
deviceCheck?: any;
|
||||||
|
playIntegrity?: any;
|
||||||
|
timestamp: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/storage",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Core storage SDK for encrypted RxDB/SQLCipher database management",
|
||||||
|
"main": "./src/index.ts",
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nx build",
|
||||||
|
"test": "nx test",
|
||||||
|
"lint": "nx lint",
|
||||||
|
"typecheck": "nx typecheck"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"rxdb": "^15.0.0",
|
||||||
|
"rxjs": "^7.8.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@core/security": "workspace:*"
|
||||||
|
},
|
||||||
|
"nx": {
|
||||||
|
"tags": ["scope:core", "type:infra", "platform:rn"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
import type { SecurityCore } from '@core/security';
|
||||||
|
import { DatabaseProvider } from './DatabaseProvider';
|
||||||
|
import { SchemaRegistry } from './SchemaRegistry';
|
||||||
|
import type { StorageConfig, CollectionSchema, DatabaseInstance } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Storage SDK
|
||||||
|
* Provides encrypted local database management with RxDB/SQLCipher
|
||||||
|
*
|
||||||
|
* Key Features (per FRD):
|
||||||
|
* - F.STC.001: Abstraction layer over RxDB/SQLite with SQLCipher encryption
|
||||||
|
* - F.STC.002: Schema registration for feature SDKs
|
||||||
|
* - F.STC.003: Conflict resolution strategies (CRDT configuration, LWW handling)
|
||||||
|
* - F.STC.004: Encrypted file vault for local media storage
|
||||||
|
* - F.STC.005: Automated database schema migration
|
||||||
|
* - F.STC.006: Incremental encryption re-keying
|
||||||
|
* - F.STC.007: Selective purge mechanisms
|
||||||
|
*/
|
||||||
|
export class StorageCore {
|
||||||
|
private config: StorageConfig;
|
||||||
|
private securityCore: SecurityCore;
|
||||||
|
private databaseProvider: DatabaseProvider;
|
||||||
|
private schemaRegistry: SchemaRegistry;
|
||||||
|
private initialized = false;
|
||||||
|
|
||||||
|
constructor(config: StorageConfig, securityCore: SecurityCore) {
|
||||||
|
this.config = config;
|
||||||
|
this.securityCore = securityCore;
|
||||||
|
this.databaseProvider = new DatabaseProvider(config, securityCore);
|
||||||
|
this.schemaRegistry = new SchemaRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.STC.001: Initialize the storage layer with encryption
|
||||||
|
*/
|
||||||
|
async initialize(): Promise<void> {
|
||||||
|
if (this.initialized) return;
|
||||||
|
|
||||||
|
await this.databaseProvider.initialize();
|
||||||
|
this.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.STC.002: Register schema for feature SDKs
|
||||||
|
*/
|
||||||
|
registerSchema(collectionName: string, schema: CollectionSchema): void {
|
||||||
|
this.schemaRegistry.register(collectionName, schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the database instance
|
||||||
|
*/
|
||||||
|
getDatabase(): DatabaseInstance {
|
||||||
|
this.ensureInitialized();
|
||||||
|
return this.databaseProvider.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.STC.002: Create collection with registered schema
|
||||||
|
*/
|
||||||
|
async createCollection(name: string): Promise<void> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
const schema = this.schemaRegistry.getSchema(name);
|
||||||
|
if (!schema) {
|
||||||
|
throw new Error(`Schema not registered for collection: ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.databaseProvider.createCollection(name, schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.STC.004: Store encrypted file
|
||||||
|
*/
|
||||||
|
async storeEncryptedFile(
|
||||||
|
filename: string,
|
||||||
|
data: Buffer,
|
||||||
|
mimeType: string,
|
||||||
|
orgId?: string
|
||||||
|
): Promise<string> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
// Encrypt file content
|
||||||
|
const encryptResult = orgId
|
||||||
|
? await this.securityCore.encryptForOrganization(data.toString('base64'), orgId)
|
||||||
|
: await this.encryptFileLocally(data);
|
||||||
|
|
||||||
|
// Store encrypted file to filesystem
|
||||||
|
const encryptedPath = await this.writeEncryptedFile(filename, encryptResult.encryptedData);
|
||||||
|
|
||||||
|
// Store metadata in database
|
||||||
|
const fileId = this.generateFileId();
|
||||||
|
const metadata = {
|
||||||
|
id: fileId,
|
||||||
|
filename,
|
||||||
|
mimeType,
|
||||||
|
size: data.length,
|
||||||
|
encryptedPath,
|
||||||
|
keyReference: JSON.stringify(encryptResult.keyReference),
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
const db = this.getDatabase();
|
||||||
|
await db.collections.fileVault.insert(metadata);
|
||||||
|
|
||||||
|
return fileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.STC.004: Retrieve encrypted file
|
||||||
|
*/
|
||||||
|
async retrieveEncryptedFile(fileId: string, orgId?: string): Promise<Buffer> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
const db = this.getDatabase();
|
||||||
|
const metadata = await db.collections.fileVault.findOne(fileId).exec();
|
||||||
|
|
||||||
|
if (!metadata) {
|
||||||
|
throw new Error(`File not found: ${fileId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read encrypted file
|
||||||
|
const encryptedData = await this.readEncryptedFile(metadata.encryptedPath);
|
||||||
|
const keyReference = JSON.parse(metadata.keyReference);
|
||||||
|
|
||||||
|
// Decrypt file content
|
||||||
|
const decryptedData = orgId
|
||||||
|
? await this.securityCore.decryptForOrganization(encryptedData, keyReference)
|
||||||
|
: await this.decryptFileLocally(encryptedData, keyReference);
|
||||||
|
|
||||||
|
return Buffer.from(decryptedData, 'base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.STC.007: Selective purge by organization
|
||||||
|
*/
|
||||||
|
async purgeOrganizationData(orgId: string): Promise<void> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
const db = this.getDatabase();
|
||||||
|
|
||||||
|
// Find all collections and purge org-specific data
|
||||||
|
for (const [collectionName, collection] of Object.entries(db.collections)) {
|
||||||
|
// Remove documents with matching orgId
|
||||||
|
await collection.find({ orgId }).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purge encrypted files belonging to organization
|
||||||
|
const orgFiles = await db.collections.fileVault
|
||||||
|
.find()
|
||||||
|
.where('keyReference')
|
||||||
|
.regex(new RegExp(orgId))
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
for (const file of orgFiles) {
|
||||||
|
await this.deleteEncryptedFile(file.encryptedPath);
|
||||||
|
await file.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F.STC.006: Re-encrypt data with new keys
|
||||||
|
*/
|
||||||
|
async reEncryptData(orgId: string, newKeyReference: any): Promise<void> {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
// This would implement re-encryption of existing data
|
||||||
|
// when organizational keys are rotated
|
||||||
|
console.warn('Re-encryption implementation needed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sync status for collections
|
||||||
|
*/
|
||||||
|
getSyncStatus(collectionName: string): any {
|
||||||
|
this.ensureInitialized();
|
||||||
|
|
||||||
|
const db = this.getDatabase();
|
||||||
|
return db.collections[collectionName]?.find({ syncStatus: 'PENDING' });
|
||||||
|
}
|
||||||
|
|
||||||
|
private async encryptFileLocally(data: Buffer): Promise<any> {
|
||||||
|
// Implementation would use local encryption for non-org files
|
||||||
|
throw new Error('Local file encryption not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
private async decryptFileLocally(encryptedData: string, keyReference: any): Promise<string> {
|
||||||
|
// Implementation would use local decryption for non-org files
|
||||||
|
throw new Error('Local file decryption not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
private async writeEncryptedFile(filename: string, encryptedData: string): Promise<string> {
|
||||||
|
// Implementation would write to secure app documents directory
|
||||||
|
const path = `/secure/${this.generateFileId()}_${filename}`;
|
||||||
|
console.warn('File system integration needed');
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async readEncryptedFile(path: string): Promise<string> {
|
||||||
|
// Implementation would read from secure app documents directory
|
||||||
|
console.warn('File system integration needed');
|
||||||
|
return 'mock-encrypted-data';
|
||||||
|
}
|
||||||
|
|
||||||
|
private async deleteEncryptedFile(path: string): Promise<void> {
|
||||||
|
// Implementation would securely delete file
|
||||||
|
console.warn('Secure file deletion needed');
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateFileId(): string {
|
||||||
|
return `file_${Date.now()}_${Math.random().toString(36).substring(2)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ensureInitialized(): void {
|
||||||
|
if (!this.initialized) {
|
||||||
|
throw new Error('StorageCore must be initialized before use');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export { StorageCore } from './StorageCore';
|
||||||
|
export { DatabaseProvider } from './DatabaseProvider';
|
||||||
|
export { SchemaRegistry } from './SchemaRegistry';
|
||||||
|
export type {
|
||||||
|
StorageConfig,
|
||||||
|
CollectionSchema,
|
||||||
|
MigrationStrategy,
|
||||||
|
ConflictResolutionStrategy
|
||||||
|
} from './types';
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import type { RxDatabase, RxCollection } from 'rxdb';
|
||||||
|
|
||||||
|
export interface StorageConfig {
|
||||||
|
databaseName: string;
|
||||||
|
enableEncryption: boolean;
|
||||||
|
enableCRDT: boolean;
|
||||||
|
migrationStrategy: 'drop' | 'migrate';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CollectionSchema {
|
||||||
|
version: number;
|
||||||
|
title: string;
|
||||||
|
type: 'object';
|
||||||
|
properties: Record<string, any>;
|
||||||
|
required?: string[];
|
||||||
|
indexes?: string[];
|
||||||
|
migrationStrategies?: Record<number, MigrationStrategy>;
|
||||||
|
conflictResolution?: ConflictResolutionStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MigrationStrategy = (oldDoc: any) => any;
|
||||||
|
|
||||||
|
export interface ConflictResolutionStrategy {
|
||||||
|
type: 'crdt' | 'lww' | 'custom';
|
||||||
|
resolver?: (conflicts: any[]) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DatabaseInstance {
|
||||||
|
database: RxDatabase;
|
||||||
|
collections: Record<string, RxCollection>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EncryptedFileMetadata {
|
||||||
|
id: string;
|
||||||
|
filename: string;
|
||||||
|
mimeType: string;
|
||||||
|
size: number;
|
||||||
|
encryptedPath: string;
|
||||||
|
keyReference: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/sync",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"nx": { "tags": ["scope:core","type:infra"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export const SyncCore = {
|
||||||
|
// placeholder sync core
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "@core/trust",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"nx": { "tags": ["scope:core","type:infra"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const TrustCore = {};
|
||||||
@@ -0,0 +1,279 @@
|
|||||||
|
# @feature/auth Playbook
|
||||||
|
|
||||||
|
## 1. Overview
|
||||||
|
|
||||||
|
Handles Authentication (OTP, Magic Link, Federated), Session Management, and Biometrics with risk-adaptive security.
|
||||||
|
|
||||||
|
**Key Features (per FRD):**
|
||||||
|
- F.ID.001: Login, Registration, and Forgot Password flows
|
||||||
|
- F.ID.002: Configurable verification (OTP, Email, Magic Links)
|
||||||
|
- F.ID.003: Secure session token storage and rotation
|
||||||
|
- F.ID.004: Device biometrics integration (FaceID/TouchID/Android Biometrics)
|
||||||
|
- F.ID.005: Configurable "Remember Me" duration
|
||||||
|
- F.ID.006: Enhanced Magic Link security with nonce and expiry
|
||||||
|
- F.ID.007: Federated Login connectors (Google, Apple)
|
||||||
|
|
||||||
|
## 2. Setup & Dependencies
|
||||||
|
|
||||||
|
**Required Core SDKs:**
|
||||||
|
- `@core/security` - DPoP key generation and signing
|
||||||
|
- `@core/trust` - Runtime Risk Score; triggers Step-Up MFA if score is high
|
||||||
|
- `@core/policy` - Risk-adaptive policy checks
|
||||||
|
- `@core/storage` - Encrypted session storage
|
||||||
|
|
||||||
|
**Installation:**
|
||||||
|
```bash
|
||||||
|
# Install auth feature layers
|
||||||
|
pnpm add @feature/auth/domain @feature/auth/data @feature/auth/ui-rn
|
||||||
|
|
||||||
|
# Peer dependencies (automatically resolved in monorepo)
|
||||||
|
# @core/security @core/trust @core/policy @core/storage
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Core Workflow: DPoP Login and Risk Assessment
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant App
|
||||||
|
participant Auth as @feature/auth
|
||||||
|
participant Trust as @core/trust
|
||||||
|
participant Security as @core/security
|
||||||
|
participant Policy as @core/policy
|
||||||
|
participant BFF
|
||||||
|
|
||||||
|
App->>Auth: login(credentials)
|
||||||
|
Auth->>Trust: calculateRiskScore()
|
||||||
|
Trust-->>Auth: { score: 45, signals: {...} }
|
||||||
|
|
||||||
|
Auth->>Security: initializeDPoP()
|
||||||
|
Security-->>Auth: publicKey
|
||||||
|
|
||||||
|
Auth->>BFF: exchangeCredentials(creds, pubKey)
|
||||||
|
BFF-->>Auth: session + tokens
|
||||||
|
|
||||||
|
alt Risk Score > Threshold
|
||||||
|
Auth->>Policy: check('step-up-mfa', context)
|
||||||
|
Policy-->>Auth: requires_verification: true
|
||||||
|
Auth-->>App: { success: true, requiresStepUp: true }
|
||||||
|
else Low Risk
|
||||||
|
Auth-->>App: { success: true, session }
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Integration Points
|
||||||
|
|
||||||
|
### @core/security Integration
|
||||||
|
```typescript
|
||||||
|
// DPoP key generation and signing
|
||||||
|
const publicKey = await this.authRepository.initializeDPoP();
|
||||||
|
const signedProof = await this.securityCore.signDPoPProof('POST', '/auth/login', accessToken);
|
||||||
|
```
|
||||||
|
|
||||||
|
### @core/trust Integration
|
||||||
|
```typescript
|
||||||
|
// Risk assessment for adaptive authentication
|
||||||
|
const { score, signals } = await this.trustRepository.calculateRiskScore();
|
||||||
|
const requiresStepUp = this.shouldRequireStepUp(score, signals);
|
||||||
|
```
|
||||||
|
|
||||||
|
### @core/policy Integration
|
||||||
|
```typescript
|
||||||
|
// Risk-adaptive policy checks
|
||||||
|
const allowed = await this.policyClient.check('login', 'User', {
|
||||||
|
riskScore: 60,
|
||||||
|
deviceSignals: signals
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Policy Enforcement Examples
|
||||||
|
|
||||||
|
**Risk-Adaptive Login:**
|
||||||
|
```typescript
|
||||||
|
// Low risk (score < 50): Standard login
|
||||||
|
await policyClient.check('login', 'User', { riskScore: 35 }); // → true
|
||||||
|
|
||||||
|
// Medium risk (50-75): Email verification
|
||||||
|
await policyClient.check('login', 'User', { riskScore: 65 }); // → requires email MFA
|
||||||
|
|
||||||
|
// High risk (75+): OTP + Device attestation
|
||||||
|
await policyClient.check('login', 'User', { riskScore: 85 }); // → requires OTP + attestation
|
||||||
|
```
|
||||||
|
|
||||||
|
**Organization Access:**
|
||||||
|
```typescript
|
||||||
|
// Check organization membership with role-based permissions
|
||||||
|
await policyClient.check('access-org', 'Organization', {
|
||||||
|
orgId: 'org-123',
|
||||||
|
userRole: 'member',
|
||||||
|
riskScore: 40
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. API Usage Examples
|
||||||
|
|
||||||
|
### Basic Login Flow
|
||||||
|
```typescript
|
||||||
|
import { LoginUseCase } from '@feature/auth/domain';
|
||||||
|
import { AuthRepository } from '@feature/auth/data';
|
||||||
|
|
||||||
|
const authRepo = new AuthRepository(securityCore, bffClient);
|
||||||
|
const trustRepo = new TrustRepository(trustCore);
|
||||||
|
const loginUseCase = new LoginUseCase(authRepo, trustRepo, config);
|
||||||
|
|
||||||
|
const result = await loginUseCase.execute({
|
||||||
|
identifier: 'user@example.com',
|
||||||
|
password: 'secure_password',
|
||||||
|
deviceId: 'device-uuid'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
if (result.requiresStepUp) {
|
||||||
|
// Handle step-up MFA flow
|
||||||
|
console.log('Additional verification required:', result.verificationMethod);
|
||||||
|
} else {
|
||||||
|
// Login successful
|
||||||
|
console.log('User session:', result.session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Biometric Authentication
|
||||||
|
```typescript
|
||||||
|
import { BiometricUseCase } from '@feature/auth/domain';
|
||||||
|
|
||||||
|
const biometricUseCase = new BiometricUseCase(authRepo, biometricConfig);
|
||||||
|
|
||||||
|
const result = await biometricUseCase.authenticate({
|
||||||
|
promptMessage: 'Authenticate to access LynkedUp',
|
||||||
|
fallbackToPassword: true
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Magic Link Flow
|
||||||
|
```typescript
|
||||||
|
// Generate magic link
|
||||||
|
const magicLink = await authRepo.generateMagicLink('user@example.com');
|
||||||
|
|
||||||
|
// Verify magic link (typically called from deep link handler)
|
||||||
|
const result = await loginUseCase.executeWithMagicLink(token, nonce);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. Configuration
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const authConfig: AuthConfig = {
|
||||||
|
requireEmailVerification: true,
|
||||||
|
requirePhoneVerification: false,
|
||||||
|
biometrics: {
|
||||||
|
enabled: true,
|
||||||
|
fallbackToPassword: true,
|
||||||
|
promptMessage: 'Authenticate with LynkedUp'
|
||||||
|
},
|
||||||
|
rememberMeDays: 30,
|
||||||
|
maxLoginAttempts: 5,
|
||||||
|
lockoutDurationMinutes: 15
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. Error Handling
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Standard error codes returned by AuthResult
|
||||||
|
switch (result.errorCode) {
|
||||||
|
case 'INVALID_CREDENTIALS':
|
||||||
|
// Handle invalid login
|
||||||
|
break;
|
||||||
|
case 'ACCOUNT_LOCKED':
|
||||||
|
// Handle account lockout
|
||||||
|
break;
|
||||||
|
case 'VERIFICATION_REQUIRED':
|
||||||
|
// Handle unverified account
|
||||||
|
break;
|
||||||
|
case 'DEVICE_NOT_TRUSTED':
|
||||||
|
// Handle untrusted device
|
||||||
|
break;
|
||||||
|
case 'POLICY_VIOLATION':
|
||||||
|
// Handle policy-based denial
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. Testing Strategy
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
```typescript
|
||||||
|
// Domain layer testing (LoginUseCase)
|
||||||
|
describe('LoginUseCase', () => {
|
||||||
|
it('should require step-up for high risk score', async () => {
|
||||||
|
mockTrustRepo.calculateRiskScore.mockResolvedValue({ score: 85, signals: {} });
|
||||||
|
|
||||||
|
const result = await loginUseCase.execute(validCredentials);
|
||||||
|
|
||||||
|
expect(result.requiresStepUp).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Contract Tests
|
||||||
|
```typescript
|
||||||
|
// Data layer testing against mocked BFF
|
||||||
|
import { setupServer } from 'msw/node';
|
||||||
|
import { graphql } from 'msw';
|
||||||
|
|
||||||
|
const server = setupServer(
|
||||||
|
graphql.mutation('Login', (req, res, ctx) => {
|
||||||
|
return res(ctx.data({
|
||||||
|
login: {
|
||||||
|
accessToken: 'mock-token',
|
||||||
|
user: mockUser
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. Security Notes
|
||||||
|
|
||||||
|
**Critical Security Requirements:**
|
||||||
|
- Private keys MUST remain in the Secure Enclave/TEE
|
||||||
|
- Magic links MUST enforce nonce and expiry (see F.ID.006)
|
||||||
|
- DPoP proofs MUST be bound to specific HTTP requests
|
||||||
|
- Session tokens MUST be stored in hardware-backed keychain
|
||||||
|
- Step-up MFA triggers MUST be policy-driven, not hardcoded
|
||||||
|
|
||||||
|
**Risk Signals Handling:**
|
||||||
|
- Root/Jailbreak detection → Immediate step-up required
|
||||||
|
- Device attestation failure → Block access + notify admin
|
||||||
|
- Geolocation deviation → Email verification required
|
||||||
|
- New device → SMS OTP required
|
||||||
|
|
||||||
|
## 11. Troubleshooting
|
||||||
|
|
||||||
|
**Common Issues:**
|
||||||
|
|
||||||
|
1. **"SecurityCore must be initialized"**
|
||||||
|
- Ensure `securityCore.initialize()` is called before auth operations
|
||||||
|
|
||||||
|
2. **"DPoP key generation failed"**
|
||||||
|
- Verify hardware-backed storage is available
|
||||||
|
- Check device security settings (passcode/biometrics enabled)
|
||||||
|
|
||||||
|
3. **"Policy evaluation failed"**
|
||||||
|
- Verify policy bundles are cached locally
|
||||||
|
- Check network connectivity for policy updates
|
||||||
|
|
||||||
|
4. **Biometric authentication unavailable**
|
||||||
|
- Verify device biometric enrollment
|
||||||
|
- Check app permissions for biometric access
|
||||||
|
|
||||||
|
## 12. Performance Considerations
|
||||||
|
|
||||||
|
- **Key Operations**: DPoP key generation (one-time, ~100ms)
|
||||||
|
- **Risk Assessment**: Device evaluation (~50-200ms depending on signals)
|
||||||
|
- **Policy Evaluation**: Local cache lookup (~1-5ms)
|
||||||
|
- **Session Storage**: Keychain operations (~10-50ms)
|
||||||
|
|
||||||
|
**Optimization Tips:**
|
||||||
|
- Cache risk assessment results for 5-10 minutes
|
||||||
|
- Pre-warm DPoP keys during app initialization
|
||||||
|
- Batch policy evaluations when possible
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/auth/data",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const AuthData = {};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/auth/domain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Authentication domain logic - pure business rules and use cases",
|
||||||
|
"main": "./src/index.ts",
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nx build",
|
||||||
|
"test": "nx test",
|
||||||
|
"lint": "nx lint",
|
||||||
|
"typecheck": "nx typecheck"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": "^9.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/uuid": "^9.0.7"
|
||||||
|
},
|
||||||
|
"nx": {
|
||||||
|
"tags": ["scope:feature", "type:domain", "platform:shared"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
export interface User {
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
phoneNumber?: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
isEmailVerified: boolean;
|
||||||
|
isPhoneVerified: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
lastLoginAt?: string;
|
||||||
|
profilePictureUrl?: string;
|
||||||
|
organizations: UserOrganization[];
|
||||||
|
preferences: UserPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserOrganization {
|
||||||
|
orgId: string;
|
||||||
|
orgName: string;
|
||||||
|
role: string;
|
||||||
|
permissions: string[];
|
||||||
|
joinedAt: string;
|
||||||
|
status: 'active' | 'suspended' | 'pending';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserPreferences {
|
||||||
|
language: string;
|
||||||
|
timezone: string;
|
||||||
|
theme: 'light' | 'dark' | 'system';
|
||||||
|
notifications: NotificationPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationPreferences {
|
||||||
|
email: boolean;
|
||||||
|
push: boolean;
|
||||||
|
sms: boolean;
|
||||||
|
marketing: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuthResult {
|
||||||
|
success: boolean;
|
||||||
|
session?: any;
|
||||||
|
requiresVerification?: boolean;
|
||||||
|
verificationMethod?: VerificationMethod;
|
||||||
|
errorCode?: string;
|
||||||
|
errorMessage?: string;
|
||||||
|
nextSteps?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VerificationMethod =
|
||||||
|
| { type: 'otp'; target: string }
|
||||||
|
| { type: 'email'; target: string }
|
||||||
|
| { type: 'biometric' }
|
||||||
|
| { type: 'magic_link'; target: string };
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export const AuthDomain = {};
|
||||||
|
import { LoginUseCase } from './usecases/LoginUseCase';
|
||||||
|
import { RegistrationUseCase } from './usecases/RegistrationUseCase';
|
||||||
|
import { SessionUseCase } from './usecases/SessionUseCase';
|
||||||
|
import { BiometricUseCase } from './usecases/BiometricUseCase';
|
||||||
|
|
||||||
|
export { LoginUseCase, RegistrationUseCase, SessionUseCase, BiometricUseCase };
|
||||||
|
export type {
|
||||||
|
IAuthRepository,
|
||||||
|
ITrustRepository,
|
||||||
|
Credentials,
|
||||||
|
UserSession,
|
||||||
|
BiometricConfig,
|
||||||
|
AuthConfig
|
||||||
|
} from './interfaces';
|
||||||
|
export type {
|
||||||
|
User,
|
||||||
|
AuthResult,
|
||||||
|
VerificationMethod
|
||||||
|
} from './entities';
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import type { User, AuthResult } from './entities';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository interface that the data layer must implement
|
||||||
|
* Following clean architecture principles - domain defines the contract
|
||||||
|
*/
|
||||||
|
export interface IAuthRepository {
|
||||||
|
// F.ID.004: DPoP initialization
|
||||||
|
initializeDPoP(): Promise<string>;
|
||||||
|
|
||||||
|
// F.ID.001: Login flows
|
||||||
|
exchangeCredentialsForToken(creds: Credentials, pubKey: string): Promise<UserSession>;
|
||||||
|
|
||||||
|
// F.ID.002: Verification flows
|
||||||
|
sendOTPVerification(phoneNumber: string): Promise<void>;
|
||||||
|
verifyOTP(phoneNumber: string, code: string): Promise<boolean>;
|
||||||
|
sendEmailVerification(email: string): Promise<void>;
|
||||||
|
verifyEmail(email: string, token: string): Promise<boolean>;
|
||||||
|
|
||||||
|
// Magic Links (F.ID.006 - Enhanced security)
|
||||||
|
generateMagicLink(email: string): Promise<string>;
|
||||||
|
verifyMagicLink(token: string, nonce: string): Promise<UserSession>;
|
||||||
|
|
||||||
|
// F.ID.007: Federated login
|
||||||
|
authenticateWithProvider(provider: 'google' | 'apple', token: string): Promise<UserSession>;
|
||||||
|
|
||||||
|
// Session management
|
||||||
|
storeSession(session: UserSession): Promise<void>;
|
||||||
|
getSession(): Promise<UserSession | null>;
|
||||||
|
refreshSession(refreshToken: string): Promise<UserSession>;
|
||||||
|
revokeSession(): Promise<void>;
|
||||||
|
|
||||||
|
// F.ID.005: Remember me functionality
|
||||||
|
enableRememberMe(duration: number): Promise<void>;
|
||||||
|
disableRememberMe(): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trust/Risk assessment interface
|
||||||
|
*/
|
||||||
|
export interface ITrustRepository {
|
||||||
|
calculateRiskScore(): Promise<{ score: number; signals: Record<string, any> }>;
|
||||||
|
performDeviceAttestation(): Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Credentials {
|
||||||
|
identifier: string; // email or phone
|
||||||
|
password?: string;
|
||||||
|
biometricSignature?: string;
|
||||||
|
deviceId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserSession {
|
||||||
|
userId: string;
|
||||||
|
accessToken: string;
|
||||||
|
refreshToken: string;
|
||||||
|
expiresAt: string;
|
||||||
|
user: User;
|
||||||
|
riskScore?: number;
|
||||||
|
requiresStepUp?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BiometricConfig {
|
||||||
|
enabled: boolean;
|
||||||
|
fallbackToPassword: boolean;
|
||||||
|
promptMessage: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuthConfig {
|
||||||
|
requireEmailVerification: boolean;
|
||||||
|
requirePhoneVerification: boolean;
|
||||||
|
biometrics: BiometricConfig;
|
||||||
|
rememberMeDays: number;
|
||||||
|
maxLoginAttempts: number;
|
||||||
|
lockoutDurationMinutes: number;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export class BiometricUseCase {
|
||||||
|
async verify(signature: string) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
import type { IAuthRepository, ITrustRepository, Credentials, UserSession, AuthConfig } from '../interfaces';
|
||||||
|
import type { AuthResult } from '../entities';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login Use Case - Pure business logic
|
||||||
|
* Orchestrates the login flow including risk assessment and DPoP initialization
|
||||||
|
*
|
||||||
|
* Features implemented (per FRD):
|
||||||
|
* - F.ID.001: Login flows
|
||||||
|
* - F.ID.004: DPoP integration
|
||||||
|
* - Risk-adaptive authentication
|
||||||
|
* - Step-up MFA based on risk score
|
||||||
|
*/
|
||||||
|
export class LoginUseCase {
|
||||||
|
constructor(
|
||||||
|
private authRepository: IAuthRepository,
|
||||||
|
private trustRepository: ITrustRepository,
|
||||||
|
private config: AuthConfig
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute login flow with risk assessment
|
||||||
|
*/
|
||||||
|
async execute(credentials: Credentials): Promise<AuthResult> {
|
||||||
|
try {
|
||||||
|
// 1. Risk Assessment (F.TR.004 from Trust SDK)
|
||||||
|
const { score: riskScore, signals } = await this.trustRepository.calculateRiskScore();
|
||||||
|
|
||||||
|
// 2. Initialize DPoP (F.ID.004 / F.SC.004)
|
||||||
|
const publicKey = await this.authRepository.initializeDPoP();
|
||||||
|
|
||||||
|
// 3. Attempt authentication
|
||||||
|
const session = await this.authRepository.exchangeCredentialsForToken(credentials, publicKey);
|
||||||
|
|
||||||
|
// 4. Enhance session with risk information
|
||||||
|
const enhancedSession: UserSession = {
|
||||||
|
...session,
|
||||||
|
riskScore,
|
||||||
|
requiresStepUp: this.shouldRequireStepUp(riskScore, signals)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 5. Store session
|
||||||
|
await this.authRepository.storeSession(enhancedSession);
|
||||||
|
|
||||||
|
// 6. Check if step-up authentication is required
|
||||||
|
if (enhancedSession.requiresStepUp) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
session: enhancedSession,
|
||||||
|
requiresVerification: true,
|
||||||
|
verificationMethod: this.determineStepUpMethod(signals),
|
||||||
|
nextSteps: ['Complete additional verification to proceed']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Enable Remember Me if configured
|
||||||
|
if (this.config.rememberMeDays > 0) {
|
||||||
|
await this.authRepository.enableRememberMe(this.config.rememberMeDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
session: enhancedSession
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return this.handleLoginError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Biometric login flow
|
||||||
|
*/
|
||||||
|
async executeWithBiometrics(biometricSignature: string, deviceId: string): Promise<AuthResult> {
|
||||||
|
const credentials: Credentials = {
|
||||||
|
identifier: 'biometric',
|
||||||
|
biometricSignature,
|
||||||
|
deviceId
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.execute(credentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Magic link login flow (F.ID.006)
|
||||||
|
*/
|
||||||
|
async executeWithMagicLink(token: string, nonce: string): Promise<AuthResult> {
|
||||||
|
try {
|
||||||
|
const session = await this.authRepository.verifyMagicLink(token, nonce);
|
||||||
|
await this.authRepository.storeSession(session);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
session
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return this.handleLoginError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Federated login flow (F.ID.007)
|
||||||
|
*/
|
||||||
|
async executeWithProvider(provider: 'google' | 'apple', token: string): Promise<AuthResult> {
|
||||||
|
try {
|
||||||
|
const session = await this.authRepository.authenticateWithProvider(provider, token);
|
||||||
|
await this.authRepository.storeSession(session);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
session
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return this.handleLoginError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private shouldRequireStepUp(riskScore: number, signals: Record<string, any>): boolean {
|
||||||
|
// Risk-based step-up logic
|
||||||
|
if (riskScore > 75) return true;
|
||||||
|
if (signals.isRooted || signals.isEmulator) return true;
|
||||||
|
if (signals.attestationFailed) return true;
|
||||||
|
if (signals.geoDeviation && riskScore > 50) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private determineStepUpMethod(signals: Record<string, any>) {
|
||||||
|
// Determine the most appropriate step-up method based on risk signals
|
||||||
|
if (signals.suspiciousLocation) {
|
||||||
|
return { type: 'otp' as const, target: 'phone' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signals.newDevice) {
|
||||||
|
return { type: 'email' as const, target: 'email' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to biometric if available
|
||||||
|
return { type: 'biometric' as const };
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleLoginError(error: any): AuthResult {
|
||||||
|
console.error('Login failed:', error);
|
||||||
|
|
||||||
|
// Map specific errors to user-friendly messages
|
||||||
|
if (error.code === 'INVALID_CREDENTIALS') {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errorCode: 'INVALID_CREDENTIALS',
|
||||||
|
errorMessage: 'Invalid email or password'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.code === 'ACCOUNT_LOCKED') {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errorCode: 'ACCOUNT_LOCKED',
|
||||||
|
errorMessage: 'Account is temporarily locked due to multiple failed attempts'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.code === 'VERIFICATION_REQUIRED') {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
requiresVerification: true,
|
||||||
|
verificationMethod: error.verificationMethod,
|
||||||
|
errorMessage: 'Account verification required'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errorCode: 'UNKNOWN_ERROR',
|
||||||
|
errorMessage: 'An unexpected error occurred'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export class RegistrationUseCase {
|
||||||
|
async execute(payload: any) {
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export class SessionUseCase {
|
||||||
|
async getCurrent(sessionId: string) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/auth/ui-rn",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const AuthUI = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/location/domain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const LocationDomain = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/location/ui-rn",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const LocationUI = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/media/domain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const MediaDomain = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/media/ui-rn",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const MediaUI = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/memberships/domain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const MembershipsDomain = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/memberships/ui-rn",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const MembershipsUI = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/messaging/data",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const MessagingData = {};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "@feature/messaging/domain",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"main": "src/index.ts"
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user