t44 0.2.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of t44 might be problematic. Click here for more details.

Files changed (86) hide show
  1. package/LICENSE.md +203 -0
  2. package/README.md +154 -0
  3. package/bin/activate +36 -0
  4. package/bin/activate.ts +30 -0
  5. package/bin/postinstall.sh +19 -0
  6. package/bin/shell +27 -0
  7. package/bin/t44 +27 -0
  8. package/caps/HomeRegistry.v0.ts +298 -0
  9. package/caps/OpenApiSchema.v0.ts +192 -0
  10. package/caps/ProjectDeployment.v0.ts +363 -0
  11. package/caps/ProjectDevelopment.v0.ts +246 -0
  12. package/caps/ProjectPublishing.v0.ts +307 -0
  13. package/caps/ProjectRack.v0.ts +128 -0
  14. package/caps/WorkspaceCli.v0.ts +391 -0
  15. package/caps/WorkspaceConfig.v0.ts +626 -0
  16. package/caps/WorkspaceConfig.yaml +53 -0
  17. package/caps/WorkspaceConnection.v0.ts +240 -0
  18. package/caps/WorkspaceEntityConfig.v0.ts +64 -0
  19. package/caps/WorkspaceEntityFact.v0.ts +193 -0
  20. package/caps/WorkspaceInfo.v0.ts +554 -0
  21. package/caps/WorkspaceInit.v0.ts +30 -0
  22. package/caps/WorkspaceKey.v0.ts +186 -0
  23. package/caps/WorkspaceProjects.v0.ts +455 -0
  24. package/caps/WorkspacePrompt.v0.ts +396 -0
  25. package/caps/WorkspaceShell.sh +39 -0
  26. package/caps/WorkspaceShell.v0.ts +104 -0
  27. package/caps/WorkspaceShell.yaml +65 -0
  28. package/caps/WorkspaceShellCli.v0.ts +109 -0
  29. package/caps/WorkspaceTest.v0.ts +167 -0
  30. package/caps/providers/LICENSE.md +8 -0
  31. package/caps/providers/README.md +2 -0
  32. package/caps/providers/bunny.net/ProjectDeployment.v0.ts +328 -0
  33. package/caps/providers/bunny.net/api-pull.v0.test.ts +319 -0
  34. package/caps/providers/bunny.net/api-pull.v0.ts +161 -0
  35. package/caps/providers/bunny.net/api-storage.v0.test.ts +168 -0
  36. package/caps/providers/bunny.net/api-storage.v0.ts +245 -0
  37. package/caps/providers/bunny.net/api.v0.ts +95 -0
  38. package/caps/providers/dynadot.com/ProjectDeployment.v0.ts +207 -0
  39. package/caps/providers/dynadot.com/api-domains.v0.test.ts +147 -0
  40. package/caps/providers/dynadot.com/api-domains.v0.ts +137 -0
  41. package/caps/providers/dynadot.com/api.v0.ts +88 -0
  42. package/caps/providers/git-scm.com/ProjectPublishing.v0.ts +231 -0
  43. package/caps/providers/github.com/ProjectPublishing.v0.ts +75 -0
  44. package/caps/providers/github.com/api.v0.ts +90 -0
  45. package/caps/providers/npmjs.com/ProjectPublishing.v0.ts +741 -0
  46. package/caps/providers/vercel.com/ProjectDeployment.v0.ts +339 -0
  47. package/caps/providers/vercel.com/api.v0.test.ts +67 -0
  48. package/caps/providers/vercel.com/api.v0.ts +132 -0
  49. package/caps/providers/vercel.com/bun.lock +194 -0
  50. package/caps/providers/vercel.com/package.json +10 -0
  51. package/caps/providers/vercel.com/project.v0.test.ts +108 -0
  52. package/caps/providers/vercel.com/project.v0.ts +150 -0
  53. package/caps/providers/vercel.com/tsconfig.json +28 -0
  54. package/docs/Overview.drawio +189 -0
  55. package/docs/Overview.svg +4 -0
  56. package/lib/crypto.ts +53 -0
  57. package/lib/openapi.ts +132 -0
  58. package/lib/ucan.ts +137 -0
  59. package/package.json +41 -0
  60. package/structs/HomeRegistryConfig.v0.ts +27 -0
  61. package/structs/ProjectDeploymentConfig.v0.ts +27 -0
  62. package/structs/ProjectDeploymentFact.v0.ts +110 -0
  63. package/structs/ProjectPublishingFact.v0.ts +69 -0
  64. package/structs/ProjectRackConfig.v0.ts +27 -0
  65. package/structs/WorkspaceCliConfig.v0.ts +27 -0
  66. package/structs/WorkspaceConfig.v0.ts +27 -0
  67. package/structs/WorkspaceKeyConfig.v0.ts +27 -0
  68. package/structs/WorkspaceMappings.v0.ts +27 -0
  69. package/structs/WorkspaceProjectsConfig.v0.ts +27 -0
  70. package/structs/WorkspaceRepositories.v0.ts +27 -0
  71. package/structs/WorkspaceShellConfig.v0.ts +45 -0
  72. package/structs/providers/LICENSE.md +8 -0
  73. package/structs/providers/README.md +2 -0
  74. package/structs/providers/bunny.net/ProjectDeploymentFact.v0.ts +41 -0
  75. package/structs/providers/bunny.net/WorkspaceConnectionConfig.v0.ts +42 -0
  76. package/structs/providers/dynadot.com/DomainFact.v0.ts +146 -0
  77. package/structs/providers/dynadot.com/WorkspaceConnectionConfig.v0.ts +41 -0
  78. package/structs/providers/git-scm.com/ProjectPublishingFact.v0.ts +46 -0
  79. package/structs/providers/github.com/ProjectPublishingFact.v0.ts +52 -0
  80. package/structs/providers/github.com/WorkspaceConnectionConfig.v0.ts +42 -0
  81. package/structs/providers/npmjs.com/ProjectPublishingFact.v0.ts +48 -0
  82. package/structs/providers/vercel.com/ProjectDeploymentFact.v0.ts +38 -0
  83. package/structs/providers/vercel.com/WorkspaceConnectionConfig.v0.ts +48 -0
  84. package/tsconfig.json +28 -0
  85. package/workspace-rt.ts +134 -0
  86. package/workspace.yaml +5 -0
package/lib/crypto.ts ADDED
@@ -0,0 +1,53 @@
1
+
2
+ import * as crypto from 'crypto'
3
+
4
+ /**
5
+ * Encrypt a string using AES-256-GCM with a key derived from the private key
6
+ */
7
+ export function encryptString(plaintext: string, privateKeyBase64: string): string {
8
+ // Derive a 32-byte symmetric key from the private key using SHA-256
9
+ const keyBytes = Buffer.from(privateKeyBase64, 'base64')
10
+ const symmetricKey = crypto.createHash('sha256').update(keyBytes).digest()
11
+
12
+ // Generate a random IV
13
+ const iv = crypto.randomBytes(16)
14
+
15
+ // Encrypt using AES-256-GCM
16
+ const cipher = crypto.createCipheriv('aes-256-gcm', symmetricKey, iv)
17
+ const encrypted = Buffer.concat([
18
+ cipher.update(plaintext, 'utf8'),
19
+ cipher.final()
20
+ ])
21
+ const authTag = cipher.getAuthTag()
22
+
23
+ // Combine IV + authTag + encrypted data and encode as base64
24
+ const combined = Buffer.concat([iv, authTag, encrypted])
25
+ return combined.toString('base64')
26
+ }
27
+
28
+ /**
29
+ * Decrypt a string using AES-256-GCM with a key derived from the private key
30
+ */
31
+ export function decryptString(ciphertext: string, privateKeyBase64: string): string {
32
+ // Derive the same symmetric key from the private key
33
+ const keyBytes = Buffer.from(privateKeyBase64, 'base64')
34
+ const symmetricKey = crypto.createHash('sha256').update(keyBytes).digest()
35
+
36
+ // Decode the combined data
37
+ const combined = Buffer.from(ciphertext, 'base64')
38
+
39
+ // Extract IV (16 bytes), authTag (16 bytes), and encrypted data
40
+ const iv = combined.subarray(0, 16)
41
+ const authTag = combined.subarray(16, 32)
42
+ const encrypted = combined.subarray(32)
43
+
44
+ // Decrypt using AES-256-GCM
45
+ const decipher = crypto.createDecipheriv('aes-256-gcm', symmetricKey, iv)
46
+ decipher.setAuthTag(authTag)
47
+ const decrypted = Buffer.concat([
48
+ decipher.update(encrypted),
49
+ decipher.final()
50
+ ])
51
+
52
+ return decrypted.toString('utf8')
53
+ }
package/lib/openapi.ts ADDED
@@ -0,0 +1,132 @@
1
+
2
+ import Ajv from 'ajv'
3
+ import addFormats from 'ajv-formats'
4
+
5
+ /**
6
+ * Convert OpenAPI schema to JSON Schema compatible format
7
+ */
8
+ export function convertOpenApiToJsonSchema(obj: any, root: any, warnings: any[] = [], visited = new WeakSet()): any {
9
+ if (typeof obj !== 'object' || obj === null) return obj
10
+ if (visited.has(obj)) return obj
11
+ visited.add(obj)
12
+
13
+ if (obj.$ref) {
14
+ const refPath = obj.$ref.replace(/^#\//, '').split('/')
15
+ let resolved = root
16
+ for (const part of refPath) {
17
+ const decodedPart = part.replace(/~1/g, '/').replace(/~0/g, '~')
18
+ resolved = resolved?.[decodedPart]
19
+ if (!resolved) {
20
+ warnings.push({
21
+ type: 'unresolved_reference',
22
+ message: `Cannot resolve reference ${obj.$ref}, using permissive schema`,
23
+ ref: obj.$ref
24
+ })
25
+ return {}
26
+ }
27
+ }
28
+ return convertOpenApiToJsonSchema(resolved, root, warnings, visited)
29
+ }
30
+
31
+ const result: any = Array.isArray(obj) ? [] : {}
32
+ for (const key in obj) {
33
+ if (key === 'nullable' && obj.nullable === true) {
34
+ if (obj.type) {
35
+ result.type = Array.isArray(obj.type) ? [...obj.type, 'null'] : [obj.type, 'null']
36
+ } else {
37
+ result.type = 'null'
38
+ }
39
+ } else if (key === 'example' || key === 'discriminator') {
40
+ continue
41
+ } else {
42
+ result[key] = convertOpenApiToJsonSchema(obj[key], root, warnings, visited)
43
+ }
44
+ }
45
+ return result
46
+ }
47
+
48
+ /**
49
+ * Create a configured AJV instance for OpenAPI/JSON Schema validation
50
+ */
51
+ export function createAjvInstance(): Ajv {
52
+ const ajv = new Ajv({
53
+ allErrors: true,
54
+ strict: false,
55
+ validateFormats: true,
56
+ logger: false
57
+ })
58
+ addFormats(ajv)
59
+ return ajv
60
+ }
61
+
62
+ /**
63
+ * Validate data against a JSON Schema
64
+ */
65
+ export function validateWithSchema(
66
+ schema: any,
67
+ data: any,
68
+ ajv?: Ajv
69
+ ): { valid: boolean; errors: any[] } {
70
+ const validator = ajv || createAjvInstance()
71
+
72
+ let validate
73
+ try {
74
+ validate = validator.compile(schema)
75
+ } catch (error: any) {
76
+ return {
77
+ valid: false,
78
+ errors: [{
79
+ type: 'schema_compilation_failed',
80
+ message: `Schema compilation failed: ${error.message}`,
81
+ error: error.message
82
+ }]
83
+ }
84
+ }
85
+
86
+ if (!validate(data)) {
87
+ const validationErrors = validate.errors?.map(err => ({
88
+ path: err.instancePath || '/',
89
+ message: err.message,
90
+ params: err.params,
91
+ keyword: err.keyword,
92
+ schemaPath: err.schemaPath
93
+ })) || []
94
+
95
+ return {
96
+ valid: false,
97
+ errors: validationErrors
98
+ }
99
+ }
100
+
101
+ return { valid: true, errors: [] }
102
+ }
103
+
104
+ /**
105
+ * Validate a single value against a property schema
106
+ */
107
+ export function validatePropertyValue(
108
+ propertySchema: any,
109
+ value: any,
110
+ propertyName: string
111
+ ): { valid: boolean; error?: string } {
112
+ // Build a minimal schema for the single property
113
+ const schema = {
114
+ type: 'object',
115
+ properties: {
116
+ [propertyName]: propertySchema
117
+ },
118
+ required: [propertyName]
119
+ }
120
+
121
+ const result = validateWithSchema(schema, { [propertyName]: value })
122
+
123
+ if (!result.valid && result.errors.length > 0) {
124
+ const error = result.errors[0]
125
+ return {
126
+ valid: false,
127
+ error: error.message || `Invalid value for ${propertyName}`
128
+ }
129
+ }
130
+
131
+ return { valid: true }
132
+ }
package/lib/ucan.ts ADDED
@@ -0,0 +1,137 @@
1
+
2
+ import { ed25519 } from '@ucanto/principal';
3
+ import * as Server from '@ucanto/server';
4
+
5
+
6
+ export async function generateKeypair(): Promise<{ did: string; privateKey: string }> {
7
+ const principal = await ed25519.generate();
8
+ // The principal itself is a Uint8Array containing the private key
9
+ const privateKeyBytes = new Uint8Array(principal as any);
10
+ return {
11
+ did: principal.did(),
12
+ privateKey: Buffer.from(privateKeyBytes).toString('base64'),
13
+ };
14
+ }
15
+
16
+ /**
17
+ * Extract DID from a base64-encoded private key
18
+ * @param privateKeyBase64 - Base64-encoded private key
19
+ * @returns The DID string
20
+ */
21
+ export function didForPrivateKey(privateKeyBase64: string): string {
22
+ const keyBytes = Buffer.from(privateKeyBase64, 'base64');
23
+ const principal = ed25519.decode(new Uint8Array(keyBytes));
24
+ return principal.did();
25
+ }
26
+
27
+ /**
28
+ * Issue a UCAN capability delegation
29
+ * @param options.issuerPrivateKey - Base64-encoded private key of the issuer
30
+ * @param options.audienceDID - DID of the audience (recipient)
31
+ * @param options.capabilities - Array of capabilities to delegate
32
+ * @param options.expiresIn - Expiration time in seconds from now (default: 1 year)
33
+ * @returns Base64-encoded UCAN token
34
+ */
35
+ export async function issueCapability(options: {
36
+ issuerPrivateKey: string;
37
+ audienceDID: string;
38
+ capabilities: Array<{ with: string; can: string }>;
39
+ expiresIn?: number;
40
+ }): Promise<string> {
41
+ // Decode the issuer's private key
42
+ const keyBytes = Buffer.from(options.issuerPrivateKey, 'base64');
43
+ const issuer = ed25519.decode(new Uint8Array(keyBytes));
44
+
45
+ // Parse the audience DID
46
+ const audience = ed25519.Verifier.parse(options.audienceDID);
47
+
48
+ const expiresIn = options.expiresIn || 365 * 24 * 60 * 60; // 1 year
49
+ const expiration = Math.floor(Date.now() / 1000) + expiresIn;
50
+
51
+ const delegation = await Server.delegate({
52
+ issuer,
53
+ audience,
54
+ capabilities: options.capabilities,
55
+ expiration,
56
+ });
57
+
58
+ const archive = await delegation.archive();
59
+ if (!archive.ok) {
60
+ throw new Error('Failed to archive delegation');
61
+ }
62
+ return Buffer.from(archive.ok).toString('base64');
63
+ };
64
+
65
+ /**
66
+ * Validate a UCAN capability delegation
67
+ * @param options.ucanToken - Base64-encoded UCAN token
68
+ * @param options.issuerDID - Expected DID of the issuer
69
+ * @param options.expectedCapability - Expected capability (optional)
70
+ * @returns Validation result with delegation details
71
+ */
72
+ export async function validateCapability(options: {
73
+ ucanToken: string;
74
+ issuerDID: string;
75
+ expectedCapability?: { can: string };
76
+ }): Promise<{
77
+ valid: boolean;
78
+ error?: string;
79
+ issuer?: string;
80
+ audience?: string;
81
+ capabilities?: Array<{ with: string; can: string }>;
82
+ expiration?: number;
83
+ }> {
84
+ try {
85
+ // Parse the UCAN from the token
86
+ const carBytes = Buffer.from(options.ucanToken, 'base64');
87
+ const result: any = await Server.Delegation.extract(carBytes);
88
+ if (!result.ok) {
89
+ return {
90
+ valid: false,
91
+ error: `Failed to parse UCAN: ${result.error.message}`,
92
+ };
93
+ }
94
+ const delegation: any = result.ok;
95
+
96
+ // Basic validation: check expiration
97
+ const now = Math.floor(Date.now() / 1000);
98
+ if (delegation.expiration && delegation.expiration < now) {
99
+ return {
100
+ valid: false,
101
+ error: 'UCAN has expired',
102
+ };
103
+ }
104
+
105
+ // Verify issuer matches expected
106
+ if (delegation.issuer.did() !== options.issuerDID) {
107
+ return {
108
+ valid: false,
109
+ error: `UCAN not issued by expected issuer. Expected: ${options.issuerDID}, Got: ${delegation.issuer.did()}`,
110
+ };
111
+ }
112
+
113
+ // Validate capability if specified
114
+ if (options.expectedCapability) {
115
+ const capability = delegation.capabilities[0];
116
+ if (capability.can !== options.expectedCapability.can) {
117
+ return {
118
+ valid: false,
119
+ error: `Invalid capability: expected '${options.expectedCapability.can}', got '${capability.can}'`,
120
+ };
121
+ }
122
+ }
123
+
124
+ return {
125
+ valid: true,
126
+ issuer: delegation.issuer.did(),
127
+ audience: delegation.audience.did(),
128
+ capabilities: delegation.capabilities,
129
+ expiration: delegation.expiration,
130
+ };
131
+ } catch (error: any) {
132
+ return {
133
+ valid: false,
134
+ error: `Failed to validate UCAN: ${error.message}`,
135
+ };
136
+ }
137
+ }
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "t44",
3
+ "version": "0.2.0-rc.1",
4
+ "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/Stream44/t44.git"
8
+ },
9
+ "type": "module",
10
+ "bin": {
11
+ "t44": "./bin/t44"
12
+ },
13
+ "exports": {
14
+ "./caps/WorkspaceConfig.v0": "./caps/WorkspaceConfig.v0.ts"
15
+ },
16
+ "dependencies": {
17
+ "js-yaml": "^4.1.0",
18
+ "commander": "^14.0.0",
19
+ "chalk": "^5.6.2",
20
+ "dotenv": "^17.2.3",
21
+ "fast-glob": "^3.3.3",
22
+ "inquirer": "^12.4.0",
23
+ "@ucanto/principal": "^9.0.3",
24
+ "@ucanto/server": "^11.0.3",
25
+ "t44": "^0.2.0-rc.1",
26
+ "@stream44.studio/encapsulate": "^0.2.0-rc.5"
27
+ },
28
+ "devDependencies": {
29
+ "@types/bun": "^1.3.4",
30
+ "@types/node": "^25.0.3",
31
+ "@types/js-yaml": "^4.0.9",
32
+ "bun-types": "^1.3.4",
33
+ "upload-to-bunny": "^2.1.0",
34
+ "axios": "^1.13.4",
35
+ "vercel": "^50.4.9",
36
+ "turbo": "^2.7.5"
37
+ },
38
+ "workspaces": [
39
+ "caps/providers/vercel.com"
40
+ ]
41
+ }
@@ -0,0 +1,27 @@
1
+
2
+ export async function capsule({
3
+ encapsulate,
4
+ CapsulePropertyTypes,
5
+ makeImportStack
6
+ }: any) {
7
+ return encapsulate({
8
+ '#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
9
+ '#': {
10
+ capsuleName: {
11
+ type: CapsulePropertyTypes.Literal,
12
+ value: capsule['#']
13
+ },
14
+ schema: {
15
+ type: CapsulePropertyTypes.Literal,
16
+ value: {}
17
+ },
18
+ }
19
+ }
20
+ }, {
21
+ extendsCapsule: 't44/caps/WorkspaceEntityConfig.v0',
22
+ importMeta: import.meta,
23
+ importStack: makeImportStack(),
24
+ capsuleName: capsule['#'],
25
+ })
26
+ }
27
+ capsule['#'] = 't44/structs/HomeRegistryConfig.v0'
@@ -0,0 +1,27 @@
1
+
2
+ export async function capsule({
3
+ encapsulate,
4
+ CapsulePropertyTypes,
5
+ makeImportStack
6
+ }: any) {
7
+ return encapsulate({
8
+ '#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
9
+ '#': {
10
+ capsuleName: {
11
+ type: CapsulePropertyTypes.Literal,
12
+ value: capsule['#']
13
+ },
14
+ schema: {
15
+ type: CapsulePropertyTypes.Literal,
16
+ value: {}
17
+ },
18
+ }
19
+ }
20
+ }, {
21
+ extendsCapsule: 't44/caps/WorkspaceEntityConfig.v0',
22
+ importMeta: import.meta,
23
+ importStack: makeImportStack(),
24
+ capsuleName: capsule['#'],
25
+ })
26
+ }
27
+ capsule['#'] = 't44/structs/ProjectDeploymentConfig.v0'
@@ -0,0 +1,110 @@
1
+
2
+ export async function capsule({
3
+ encapsulate,
4
+ CapsulePropertyTypes,
5
+ makeImportStack
6
+ }: any) {
7
+ return encapsulate({
8
+ '#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
9
+ '#t44/caps/OpenApiSchema.v0': {
10
+ as: 'schema',
11
+ options: {
12
+ '#': {
13
+ definitions: {
14
+ 'ProjectDeploymentStatus': {
15
+ type: 'object',
16
+ properties: {
17
+ projectName: {
18
+ type: 'string',
19
+ description: 'The name of the deployed project'
20
+ },
21
+ provider: {
22
+ type: 'string',
23
+ description: 'The deployment provider (e.g., vercel.com, bunny.net)'
24
+ },
25
+ status: {
26
+ type: 'string',
27
+ enum: ['READY', 'BUILDING', 'ERROR', 'DISABLED', 'UNKNOWN'],
28
+ description: 'Current deployment status'
29
+ },
30
+ publicUrl: {
31
+ type: 'string',
32
+ format: 'uri',
33
+ description: 'The public URL where the deployment is accessible'
34
+ },
35
+ createdAt: {
36
+ type: 'integer',
37
+ description: 'Timestamp when the deployment was created'
38
+ },
39
+ updatedAt: {
40
+ type: 'integer',
41
+ description: 'Timestamp when the deployment was last updated'
42
+ },
43
+ providerProjectId: {
44
+ type: 'string',
45
+ description: 'Provider-specific project identifier'
46
+ },
47
+ providerPortalUrl: {
48
+ type: 'string',
49
+ format: 'uri',
50
+ description: 'URL to the provider admin portal for this deployment'
51
+ },
52
+ usage: {
53
+ type: 'object',
54
+ properties: {
55
+ storageBytes: {
56
+ type: 'integer',
57
+ description: 'Storage used in bytes'
58
+ },
59
+ filesCount: {
60
+ type: 'integer',
61
+ description: 'Number of files stored'
62
+ },
63
+ bandwidthBytes: {
64
+ type: 'integer',
65
+ description: 'Bandwidth used in bytes (monthly)'
66
+ },
67
+ charges: {
68
+ type: 'number',
69
+ description: 'Monthly charges in USD'
70
+ }
71
+ },
72
+ description: 'Usage statistics for the deployment'
73
+ },
74
+ error: {
75
+ type: 'string',
76
+ description: 'Error message if status retrieval failed'
77
+ },
78
+ rawDefinitionFilepaths: {
79
+ type: 'array',
80
+ items: {
81
+ type: 'string'
82
+ },
83
+ description: 'Relative filepaths to the raw provider-specific definition files'
84
+ }
85
+ },
86
+ required: ['projectName', 'provider', 'rawDefinitionFilepaths']
87
+ }
88
+ }
89
+ }
90
+ }
91
+ },
92
+ '#': {
93
+ capsuleName: {
94
+ type: CapsulePropertyTypes.Literal,
95
+ value: capsule['#']
96
+ },
97
+ origin: {
98
+ type: CapsulePropertyTypes.Literal,
99
+ value: 'workspace.foundation'
100
+ }
101
+ }
102
+ }
103
+ }, {
104
+ extendsCapsule: 't44/caps/WorkspaceEntityFact.v0',
105
+ importMeta: import.meta,
106
+ importStack: makeImportStack(),
107
+ capsuleName: capsule['#'],
108
+ })
109
+ }
110
+ capsule['#'] = 't44/structs/ProjectDeploymentFact.v0'
@@ -0,0 +1,69 @@
1
+
2
+ export async function capsule({
3
+ encapsulate,
4
+ CapsulePropertyTypes,
5
+ makeImportStack
6
+ }: any) {
7
+ return encapsulate({
8
+ '#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
9
+ '#t44/caps/OpenApiSchema.v0': {
10
+ as: 'schema',
11
+ options: {
12
+ '#': {
13
+ definitions: {
14
+ 'ProjectPublishingStatus': {
15
+ type: 'object',
16
+ properties: {
17
+ projectName: {
18
+ type: 'string',
19
+ description: 'The name of the published project'
20
+ },
21
+ provider: {
22
+ type: 'string',
23
+ description: 'The publishing provider (e.g., github.com, git-scm.com, npmjs.com)'
24
+ },
25
+ status: {
26
+ type: 'string',
27
+ enum: ['READY', 'PUBLISHED', 'ERROR', 'SKIPPED', 'UNKNOWN'],
28
+ description: 'Current publishing status'
29
+ },
30
+ publicUrl: {
31
+ type: 'string',
32
+ format: 'uri',
33
+ description: 'The public URL where the published resource is accessible'
34
+ },
35
+ updatedAt: {
36
+ type: 'string',
37
+ format: 'date-time',
38
+ description: 'Timestamp when the publishing was last updated'
39
+ },
40
+ error: {
41
+ type: 'string',
42
+ description: 'Error message if publishing failed'
43
+ }
44
+ },
45
+ required: ['projectName', 'provider']
46
+ }
47
+ }
48
+ }
49
+ }
50
+ },
51
+ '#': {
52
+ capsuleName: {
53
+ type: CapsulePropertyTypes.Literal,
54
+ value: capsule['#']
55
+ },
56
+ origin: {
57
+ type: CapsulePropertyTypes.Literal,
58
+ value: 'workspace.foundation'
59
+ }
60
+ }
61
+ }
62
+ }, {
63
+ extendsCapsule: 't44/caps/WorkspaceEntityFact.v0',
64
+ importMeta: import.meta,
65
+ importStack: makeImportStack(),
66
+ capsuleName: capsule['#'],
67
+ })
68
+ }
69
+ capsule['#'] = 't44/structs/ProjectPublishingFact.v0'
@@ -0,0 +1,27 @@
1
+
2
+ export async function capsule({
3
+ encapsulate,
4
+ CapsulePropertyTypes,
5
+ makeImportStack
6
+ }: any) {
7
+ return encapsulate({
8
+ '#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
9
+ '#': {
10
+ capsuleName: {
11
+ type: CapsulePropertyTypes.Literal,
12
+ value: capsule['#']
13
+ },
14
+ schema: {
15
+ type: CapsulePropertyTypes.Literal,
16
+ value: {}
17
+ },
18
+ }
19
+ }
20
+ }, {
21
+ extendsCapsule: 't44/caps/WorkspaceEntityConfig.v0',
22
+ importMeta: import.meta,
23
+ importStack: makeImportStack(),
24
+ capsuleName: capsule['#'],
25
+ })
26
+ }
27
+ capsule['#'] = 't44/structs/ProjectRackConfig.v0'
@@ -0,0 +1,27 @@
1
+
2
+ export async function capsule({
3
+ encapsulate,
4
+ CapsulePropertyTypes,
5
+ makeImportStack
6
+ }: any) {
7
+ return encapsulate({
8
+ '#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
9
+ '#': {
10
+ capsuleName: {
11
+ type: CapsulePropertyTypes.Literal,
12
+ value: capsule['#']
13
+ },
14
+ schema: {
15
+ type: CapsulePropertyTypes.Literal,
16
+ value: {}
17
+ },
18
+ }
19
+ }
20
+ }, {
21
+ extendsCapsule: 't44/caps/WorkspaceEntityConfig.v0',
22
+ importMeta: import.meta,
23
+ importStack: makeImportStack(),
24
+ capsuleName: capsule['#'],
25
+ })
26
+ }
27
+ capsule['#'] = 't44/structs/WorkspaceCliConfig.v0'
@@ -0,0 +1,27 @@
1
+
2
+ export async function capsule({
3
+ encapsulate,
4
+ CapsulePropertyTypes,
5
+ makeImportStack
6
+ }: any) {
7
+ return encapsulate({
8
+ '#@stream44.studio/encapsulate/spine-contracts/CapsuleSpineContract.v0': {
9
+ '#': {
10
+ capsuleName: {
11
+ type: CapsulePropertyTypes.Literal,
12
+ value: capsule['#']
13
+ },
14
+ schema: {
15
+ type: CapsulePropertyTypes.Literal,
16
+ value: {}
17
+ },
18
+ }
19
+ }
20
+ }, {
21
+ extendsCapsule: 't44/caps/WorkspaceEntityConfig.v0',
22
+ importMeta: import.meta,
23
+ importStack: makeImportStack(),
24
+ capsuleName: capsule['#'],
25
+ })
26
+ }
27
+ capsule['#'] = 't44/structs/WorkspaceConfig.v0'