@fractary/core 0.7.26 → 0.7.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/yaml-config.d.ts +15 -0
- package/dist/common/yaml-config.d.ts.map +1 -1
- package/dist/common/yaml-config.js.map +1 -1
- package/dist/config/__tests__/loader.test.js +84 -34
- package/dist/config/__tests__/loader.test.js.map +1 -1
- package/dist/config/defaults.d.ts +82 -2
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +112 -6
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/defaults.test.js +226 -1
- package/dist/config/defaults.test.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/loader.d.ts +8 -6
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +49 -37
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +12 -12
- package/dist/repo/config.d.ts +14 -11
- package/dist/repo/config.d.ts.map +1 -1
- package/dist/repo/config.js +59 -16
- package/dist/repo/config.js.map +1 -1
- package/dist/repo/config.test.js +9 -14
- package/dist/repo/config.test.js.map +1 -1
- package/dist/repo/path-generator.d.ts +6 -6
- package/dist/repo/path-generator.d.ts.map +1 -1
- package/dist/repo/path-generator.js +12 -8
- package/dist/repo/path-generator.js.map +1 -1
- package/dist/repo/path-generator.test.d.ts +1 -1
- package/dist/repo/path-generator.test.js +61 -82
- package/dist/repo/path-generator.test.js.map +1 -1
- package/package.json +1 -1
- package/templates/terraform/r2.tf.mustache +78 -0
- package/templates/terraform/s3.tf.mustache +204 -0
- package/templates/terraform/variables.tf.mustache +47 -0
|
@@ -40,13 +40,13 @@ const organization_js_1 = require("./organization.js");
|
|
|
40
40
|
const config_js_1 = require("./config.js");
|
|
41
41
|
const exec_file_no_throw_js_1 = require("../common/exec-file-no-throw.js");
|
|
42
42
|
/**
|
|
43
|
-
* Generate a worktree path
|
|
43
|
+
* Generate a worktree path from configuration
|
|
44
44
|
*
|
|
45
45
|
* Path generation logic:
|
|
46
46
|
* 1. If customPath is provided, use it directly
|
|
47
47
|
* 2. Load configuration (or use provided config)
|
|
48
|
-
* 3.
|
|
49
|
-
* 4. Generate
|
|
48
|
+
* 3. Resolve the worktree base location (relative to cwd or absolute)
|
|
49
|
+
* 4. Generate the worktree name using the pathPattern with substitutions
|
|
50
50
|
* 5. Return resolved absolute path
|
|
51
51
|
*
|
|
52
52
|
* @param cwd Current working directory (git repository root)
|
|
@@ -56,11 +56,11 @@ const exec_file_no_throw_js_1 = require("../common/exec-file-no-throw.js");
|
|
|
56
56
|
* @example
|
|
57
57
|
* ```typescript
|
|
58
58
|
* // Auto-detect organization and project
|
|
59
|
-
* const
|
|
60
|
-
* // Returns: /
|
|
59
|
+
* const worktreePath = await generateWorktreePath('/path/to/repo', { workId: '258' });
|
|
60
|
+
* // Returns: /path/to/repo/.claude/worktrees/work-id-258
|
|
61
61
|
*
|
|
62
62
|
* // Custom path
|
|
63
|
-
* const
|
|
63
|
+
* const worktreePath = await generateWorktreePath('/path/to/repo', {
|
|
64
64
|
* workId: '258',
|
|
65
65
|
* customPath: '/custom/path'
|
|
66
66
|
* });
|
|
@@ -85,8 +85,12 @@ async function generateWorktreePath(cwd, options) {
|
|
|
85
85
|
org = org || remoteInfo?.organization || 'local';
|
|
86
86
|
proj = proj || remoteInfo?.project || path.basename(cwd);
|
|
87
87
|
}
|
|
88
|
-
//
|
|
89
|
-
|
|
88
|
+
// Resolve worktree base location
|
|
89
|
+
let location = (0, config_js_1.expandTilde)(config.defaultLocation);
|
|
90
|
+
// Resolve relative paths against the project root (cwd)
|
|
91
|
+
if (!path.isAbsolute(location)) {
|
|
92
|
+
location = path.resolve(cwd, location);
|
|
93
|
+
}
|
|
90
94
|
const name = (0, config_js_1.applyPathPattern)(config.pathPattern, {
|
|
91
95
|
organization: org,
|
|
92
96
|
project: proj,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-generator.js","sourceRoot":"","sources":["../../src/repo/path-generator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,
|
|
1
|
+
{"version":3,"file":"path-generator.js","sourceRoot":"","sources":["../../src/repo/path-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @fractary/sdk - Path Generator Tests
|
|
4
4
|
*
|
|
5
|
-
* Tests for worktree path generation
|
|
5
|
+
* Tests for worktree path generation.
|
|
6
6
|
*/
|
|
7
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
8
|
if (k2 === undefined) k2 = k;
|
|
@@ -43,31 +43,35 @@ const path_1 = require("path");
|
|
|
43
43
|
const path_generator_js_1 = require("./path-generator.js");
|
|
44
44
|
const organization = __importStar(require("./organization.js"));
|
|
45
45
|
const config = __importStar(require("./config.js"));
|
|
46
|
-
// Mock modules
|
|
46
|
+
// Mock modules - partial mock config to keep expandTilde and applyPathPattern real
|
|
47
47
|
vitest_1.vi.mock('./organization.js');
|
|
48
|
-
vitest_1.vi.mock('./config.js')
|
|
48
|
+
vitest_1.vi.mock('./config.js', async () => {
|
|
49
|
+
const actual = await vitest_1.vi.importActual('./config.js');
|
|
50
|
+
return {
|
|
51
|
+
...actual,
|
|
52
|
+
loadRepoConfig: vitest_1.vi.fn(),
|
|
53
|
+
};
|
|
54
|
+
});
|
|
49
55
|
(0, vitest_1.describe)('generateWorktreePath', () => {
|
|
50
56
|
const HOME = '/home/testuser';
|
|
51
57
|
const CWD = '/home/testuser/projects/repo';
|
|
52
58
|
(0, vitest_1.beforeEach)(() => {
|
|
53
59
|
// Mock HOME environment variable
|
|
54
60
|
process.env.HOME = HOME;
|
|
55
|
-
// Default config mock
|
|
61
|
+
// Default config mock - returns RepoConfigExtended with worktree at top level
|
|
56
62
|
vitest_1.vi.mocked(config.loadRepoConfig).mockResolvedValue({
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
autoMigrate: false,
|
|
63
|
-
},
|
|
63
|
+
active_handler: 'github',
|
|
64
|
+
handlers: {},
|
|
65
|
+
worktree: {
|
|
66
|
+
defaultLocation: '.claude/worktrees',
|
|
67
|
+
pathPattern: 'work-id-{work-id}',
|
|
64
68
|
},
|
|
65
69
|
});
|
|
66
70
|
});
|
|
67
71
|
(0, vitest_1.afterEach)(() => {
|
|
68
72
|
vitest_1.vi.clearAllMocks();
|
|
69
73
|
});
|
|
70
|
-
(0, vitest_1.describe)('
|
|
74
|
+
(0, vitest_1.describe)('default path pattern (work-id-{id})', () => {
|
|
71
75
|
(0, vitest_1.beforeEach)(() => {
|
|
72
76
|
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue({
|
|
73
77
|
name: 'origin',
|
|
@@ -76,47 +80,25 @@ vitest_1.vi.mock('./config.js');
|
|
|
76
80
|
project: 'core',
|
|
77
81
|
});
|
|
78
82
|
});
|
|
79
|
-
(0, vitest_1.it)('should generate
|
|
83
|
+
(0, vitest_1.it)('should generate path under .claude/worktrees with work-id prefix', async () => {
|
|
80
84
|
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
81
85
|
workId: '258',
|
|
82
86
|
});
|
|
83
|
-
(0, vitest_1.expect)(path).toBe((0, path_1.join)(
|
|
87
|
+
(0, vitest_1.expect)(path).toBe((0, path_1.join)(CWD, '.claude', 'worktrees', 'work-id-258'));
|
|
84
88
|
});
|
|
85
|
-
(0, vitest_1.it)('should
|
|
89
|
+
(0, vitest_1.it)('should resolve relative location against cwd', async () => {
|
|
86
90
|
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
87
|
-
workId: '
|
|
88
|
-
organization: 'mycompany',
|
|
89
|
-
});
|
|
90
|
-
(0, vitest_1.expect)(path).toBe((0, path_1.join)(HOME, '.claude-worktrees', 'mycompany-core-258'));
|
|
91
|
-
});
|
|
92
|
-
(0, vitest_1.it)('should use provided project', async () => {
|
|
93
|
-
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
94
|
-
workId: '258',
|
|
95
|
-
project: 'backend',
|
|
96
|
-
});
|
|
97
|
-
(0, vitest_1.expect)(path).toBe((0, path_1.join)(HOME, '.claude-worktrees', 'fractary-backend-258'));
|
|
98
|
-
});
|
|
99
|
-
(0, vitest_1.it)('should use both provided organization and project', async () => {
|
|
100
|
-
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
101
|
-
workId: '258',
|
|
102
|
-
organization: 'acme',
|
|
103
|
-
project: 'webapp',
|
|
91
|
+
workId: '123',
|
|
104
92
|
});
|
|
105
|
-
(0, vitest_1.expect)(path).toBe((0, path_1.join)(
|
|
93
|
+
(0, vitest_1.expect)(path).toBe((0, path_1.join)(CWD, '.claude', 'worktrees', 'work-id-123'));
|
|
106
94
|
});
|
|
107
|
-
(0, vitest_1.it)('should fallback to
|
|
95
|
+
(0, vitest_1.it)('should fallback to defaults if no remote', async () => {
|
|
108
96
|
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue(null);
|
|
109
97
|
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
110
98
|
workId: '258',
|
|
111
99
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
(0, vitest_1.it)('should use directory basename as project if no remote', async () => {
|
|
115
|
-
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue(null);
|
|
116
|
-
const path = await (0, path_generator_js_1.generateWorktreePath)('/home/user/my-project', {
|
|
117
|
-
workId: '123',
|
|
118
|
-
});
|
|
119
|
-
(0, vitest_1.expect)(path).toBe((0, path_1.join)(HOME, '.claude-worktrees', 'local-my-project-123'));
|
|
100
|
+
// Pattern is work-id-{work-id} so org/project don't matter
|
|
101
|
+
(0, vitest_1.expect)(path).toBe((0, path_1.join)(CWD, '.claude', 'worktrees', 'work-id-258'));
|
|
120
102
|
});
|
|
121
103
|
});
|
|
122
104
|
(0, vitest_1.describe)('Custom path override', () => {
|
|
@@ -140,13 +122,11 @@ vitest_1.vi.mock('./config.js');
|
|
|
140
122
|
(0, vitest_1.describe)('Custom configuration', () => {
|
|
141
123
|
(0, vitest_1.it)('should use custom defaultLocation from config', async () => {
|
|
142
124
|
vitest_1.vi.mocked(config.loadRepoConfig).mockResolvedValue({
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
autoMigrate: false,
|
|
149
|
-
},
|
|
125
|
+
active_handler: 'github',
|
|
126
|
+
handlers: {},
|
|
127
|
+
worktree: {
|
|
128
|
+
defaultLocation: '~/my-worktrees/',
|
|
129
|
+
pathPattern: '{organization}-{project}-{work-id}',
|
|
150
130
|
},
|
|
151
131
|
});
|
|
152
132
|
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue({
|
|
@@ -162,13 +142,11 @@ vitest_1.vi.mock('./config.js');
|
|
|
162
142
|
});
|
|
163
143
|
(0, vitest_1.it)('should use custom pathPattern from config', async () => {
|
|
164
144
|
vitest_1.vi.mocked(config.loadRepoConfig).mockResolvedValue({
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
autoMigrate: false,
|
|
171
|
-
},
|
|
145
|
+
active_handler: 'github',
|
|
146
|
+
handlers: {},
|
|
147
|
+
worktree: {
|
|
148
|
+
defaultLocation: '.claude/worktrees',
|
|
149
|
+
pathPattern: '{project}/{work-id}',
|
|
172
150
|
},
|
|
173
151
|
});
|
|
174
152
|
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue({
|
|
@@ -180,14 +158,12 @@ vitest_1.vi.mock('./config.js');
|
|
|
180
158
|
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
181
159
|
workId: '258',
|
|
182
160
|
});
|
|
183
|
-
(0, vitest_1.expect)(path).toBe((0, path_1.join)(
|
|
161
|
+
(0, vitest_1.expect)(path).toBe((0, path_1.join)(CWD, '.claude', 'worktrees', 'core', '258'));
|
|
184
162
|
});
|
|
185
163
|
(0, vitest_1.it)('should pass through custom config in options', async () => {
|
|
186
164
|
const customConfig = {
|
|
187
165
|
defaultLocation: '/tmp/worktrees/',
|
|
188
166
|
pathPattern: 'wt-{work-id}',
|
|
189
|
-
legacySupport: false,
|
|
190
|
-
autoMigrate: false,
|
|
191
167
|
};
|
|
192
168
|
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue({
|
|
193
169
|
name: 'origin',
|
|
@@ -204,7 +180,15 @@ vitest_1.vi.mock('./config.js');
|
|
|
204
180
|
});
|
|
205
181
|
});
|
|
206
182
|
(0, vitest_1.describe)('Tilde expansion', () => {
|
|
207
|
-
(0, vitest_1.it)('should expand ~
|
|
183
|
+
(0, vitest_1.it)('should expand ~ in tilde-prefixed location', async () => {
|
|
184
|
+
vitest_1.vi.mocked(config.loadRepoConfig).mockResolvedValue({
|
|
185
|
+
active_handler: 'github',
|
|
186
|
+
handlers: {},
|
|
187
|
+
worktree: {
|
|
188
|
+
defaultLocation: '~/my-worktrees',
|
|
189
|
+
pathPattern: 'work-id-{work-id}',
|
|
190
|
+
},
|
|
191
|
+
});
|
|
208
192
|
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue({
|
|
209
193
|
name: 'origin',
|
|
210
194
|
url: 'git@github.com:fractary/core.git',
|
|
@@ -216,16 +200,15 @@ vitest_1.vi.mock('./config.js');
|
|
|
216
200
|
});
|
|
217
201
|
(0, vitest_1.expect)(path).not.toContain('~');
|
|
218
202
|
(0, vitest_1.expect)(path).toContain(HOME);
|
|
203
|
+
(0, vitest_1.expect)(path).toBe((0, path_1.join)(HOME, 'my-worktrees', 'work-id-258'));
|
|
219
204
|
});
|
|
220
|
-
(0, vitest_1.it)('should handle paths without tilde', async () => {
|
|
205
|
+
(0, vitest_1.it)('should handle absolute paths without tilde', async () => {
|
|
221
206
|
vitest_1.vi.mocked(config.loadRepoConfig).mockResolvedValue({
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
autoMigrate: false,
|
|
228
|
-
},
|
|
207
|
+
active_handler: 'github',
|
|
208
|
+
handlers: {},
|
|
209
|
+
worktree: {
|
|
210
|
+
defaultLocation: '/absolute/path/',
|
|
211
|
+
pathPattern: '{organization}-{project}-{work-id}',
|
|
229
212
|
},
|
|
230
213
|
});
|
|
231
214
|
vitest_1.vi.mocked(organization.getRemoteInfo).mockResolvedValue({
|
|
@@ -243,13 +226,11 @@ vitest_1.vi.mock('./config.js');
|
|
|
243
226
|
(0, vitest_1.describe)('Pattern substitution', () => {
|
|
244
227
|
(0, vitest_1.it)('should handle pattern with only work-id', async () => {
|
|
245
228
|
vitest_1.vi.mocked(config.loadRepoConfig).mockResolvedValue({
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
autoMigrate: false,
|
|
252
|
-
},
|
|
229
|
+
active_handler: 'github',
|
|
230
|
+
handlers: {},
|
|
231
|
+
worktree: {
|
|
232
|
+
defaultLocation: '~/.worktrees/',
|
|
233
|
+
pathPattern: '{work-id}',
|
|
253
234
|
},
|
|
254
235
|
});
|
|
255
236
|
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
@@ -259,13 +240,11 @@ vitest_1.vi.mock('./config.js');
|
|
|
259
240
|
});
|
|
260
241
|
(0, vitest_1.it)('should handle pattern with prefix and suffix', async () => {
|
|
261
242
|
vitest_1.vi.mocked(config.loadRepoConfig).mockResolvedValue({
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
autoMigrate: false,
|
|
268
|
-
},
|
|
243
|
+
active_handler: 'github',
|
|
244
|
+
handlers: {},
|
|
245
|
+
worktree: {
|
|
246
|
+
defaultLocation: '~/.worktrees/',
|
|
247
|
+
pathPattern: 'issue-{work-id}-branch',
|
|
269
248
|
},
|
|
270
249
|
});
|
|
271
250
|
const path = await (0, path_generator_js_1.generateWorktreePath)(CWD, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-generator.test.js","sourceRoot":"","sources":["../../src/repo/path-generator.test.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,mCAAyE;AACzE,+BAA4B;AAC5B,2DAA2D;AAC3D,gEAAkD;AAClD,oDAAsC;AAEtC,
|
|
1
|
+
{"version":3,"file":"path-generator.test.js","sourceRoot":"","sources":["../../src/repo/path-generator.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fractary/core",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.27",
|
|
4
4
|
"description": "Fractary Core SDK - Primitive operations for work tracking, repository management, logging, file storage, and documentation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Fractary Cloud Storage - Cloudflare R2
|
|
2
|
+
#
|
|
3
|
+
# This Terraform configuration creates an R2 bucket for Fractary Core
|
|
4
|
+
# file storage (docs and logs archival).
|
|
5
|
+
#
|
|
6
|
+
# Generated by: fractary-core config cloud-init --provider r2
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# cd infra/terraform
|
|
10
|
+
# terraform init
|
|
11
|
+
# terraform plan
|
|
12
|
+
# terraform apply
|
|
13
|
+
#
|
|
14
|
+
# Prerequisites:
|
|
15
|
+
# - Cloudflare API token with R2 permissions
|
|
16
|
+
# - Set CLOUDFLARE_API_TOKEN environment variable
|
|
17
|
+
|
|
18
|
+
terraform {
|
|
19
|
+
required_version = ">= 1.0"
|
|
20
|
+
|
|
21
|
+
required_providers {
|
|
22
|
+
cloudflare = {
|
|
23
|
+
source = "cloudflare/cloudflare"
|
|
24
|
+
version = "~> 4.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
provider "cloudflare" {
|
|
30
|
+
api_token = var.cloudflare_api_token
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# --- R2 Bucket ---
|
|
34
|
+
|
|
35
|
+
resource "cloudflare_r2_bucket" "fractary" {
|
|
36
|
+
account_id = var.cloudflare_account_id
|
|
37
|
+
name = var.bucket_name
|
|
38
|
+
location = var.r2_location
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# --- R2 API Token for Application Access ---
|
|
42
|
+
#
|
|
43
|
+
# Note: R2 uses S3-compatible API keys for bucket access.
|
|
44
|
+
# You can create these in the Cloudflare dashboard:
|
|
45
|
+
# Dashboard > R2 > Manage R2 API Tokens > Create API Token
|
|
46
|
+
#
|
|
47
|
+
# Set the resulting credentials in .fractary/env/.env:
|
|
48
|
+
# R2_ACCOUNT_ID=your_account_id
|
|
49
|
+
# R2_ACCESS_KEY_ID=your_access_key
|
|
50
|
+
# R2_SECRET_ACCESS_KEY=your_secret_key
|
|
51
|
+
|
|
52
|
+
# --- Lifecycle Rules ---
|
|
53
|
+
#
|
|
54
|
+
# R2 lifecycle rules are managed via the Cloudflare dashboard or API.
|
|
55
|
+
# Terraform support for R2 lifecycle rules is limited.
|
|
56
|
+
#
|
|
57
|
+
# Recommended manual configuration:
|
|
58
|
+
# - Transition archived objects to Infrequent Access after 90 days
|
|
59
|
+
# - No expiration (keep archives indefinitely)
|
|
60
|
+
#
|
|
61
|
+
# Dashboard path: R2 > {bucket} > Settings > Object lifecycle rules
|
|
62
|
+
|
|
63
|
+
# --- Outputs ---
|
|
64
|
+
|
|
65
|
+
output "bucket_name" {
|
|
66
|
+
description = "The name of the Fractary R2 bucket"
|
|
67
|
+
value = cloudflare_r2_bucket.fractary.name
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
output "r2_endpoint" {
|
|
71
|
+
description = "The S3-compatible endpoint for this R2 bucket"
|
|
72
|
+
value = "https://${var.cloudflare_account_id}.r2.cloudflarestorage.com"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
output "account_id" {
|
|
76
|
+
description = "The Cloudflare account ID"
|
|
77
|
+
value = var.cloudflare_account_id
|
|
78
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Fractary Cloud Storage - AWS S3
|
|
2
|
+
#
|
|
3
|
+
# This Terraform configuration creates an S3 bucket for Fractary Core
|
|
4
|
+
# file storage (docs and logs archival).
|
|
5
|
+
#
|
|
6
|
+
# Generated by: fractary-core config cloud-init --provider s3
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# cd infra/terraform
|
|
10
|
+
# terraform init
|
|
11
|
+
# terraform plan
|
|
12
|
+
# terraform apply
|
|
13
|
+
|
|
14
|
+
terraform {
|
|
15
|
+
required_version = ">= 1.0"
|
|
16
|
+
|
|
17
|
+
required_providers {
|
|
18
|
+
aws = {
|
|
19
|
+
source = "hashicorp/aws"
|
|
20
|
+
version = "~> 5.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
provider "aws" {
|
|
26
|
+
region = var.aws_region
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# --- S3 Bucket ---
|
|
30
|
+
|
|
31
|
+
resource "aws_s3_bucket" "fractary" {
|
|
32
|
+
bucket = var.bucket_name
|
|
33
|
+
|
|
34
|
+
tags = {
|
|
35
|
+
Name = var.bucket_name
|
|
36
|
+
ManagedBy = "fractary-core"
|
|
37
|
+
Project = var.project_name
|
|
38
|
+
Environment = "dev"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Enable versioning for data protection
|
|
43
|
+
resource "aws_s3_bucket_versioning" "fractary" {
|
|
44
|
+
bucket = aws_s3_bucket.fractary.id
|
|
45
|
+
|
|
46
|
+
versioning_configuration {
|
|
47
|
+
status = "Enabled"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Server-side encryption (AES-256)
|
|
52
|
+
resource "aws_s3_bucket_server_side_encryption_configuration" "fractary" {
|
|
53
|
+
bucket = aws_s3_bucket.fractary.id
|
|
54
|
+
|
|
55
|
+
rule {
|
|
56
|
+
apply_server_side_encryption_by_default {
|
|
57
|
+
sse_algorithm = "AES256"
|
|
58
|
+
}
|
|
59
|
+
bucket_key_enabled = true
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# Block all public access
|
|
64
|
+
resource "aws_s3_bucket_public_access_block" "fractary" {
|
|
65
|
+
bucket = aws_s3_bucket.fractary.id
|
|
66
|
+
|
|
67
|
+
block_public_acls = true
|
|
68
|
+
block_public_policy = true
|
|
69
|
+
ignore_public_acls = true
|
|
70
|
+
restrict_public_buckets = true
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Lifecycle rules for cost optimization
|
|
74
|
+
resource "aws_s3_bucket_lifecycle_configuration" "fractary" {
|
|
75
|
+
bucket = aws_s3_bucket.fractary.id
|
|
76
|
+
|
|
77
|
+
# Transition archived logs to Infrequent Access after 90 days
|
|
78
|
+
rule {
|
|
79
|
+
id = "archive-logs-transition"
|
|
80
|
+
status = "Enabled"
|
|
81
|
+
|
|
82
|
+
filter {
|
|
83
|
+
prefix = "logs/_archive/"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
transition {
|
|
87
|
+
days = 90
|
|
88
|
+
storage_class = "STANDARD_IA"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
transition {
|
|
92
|
+
days = 365
|
|
93
|
+
storage_class = "GLACIER"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Transition archived docs to Infrequent Access after 90 days
|
|
98
|
+
rule {
|
|
99
|
+
id = "archive-docs-transition"
|
|
100
|
+
status = "Enabled"
|
|
101
|
+
|
|
102
|
+
filter {
|
|
103
|
+
prefix = "docs/_archive/"
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
transition {
|
|
107
|
+
days = 90
|
|
108
|
+
storage_class = "STANDARD_IA"
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
transition {
|
|
112
|
+
days = 365
|
|
113
|
+
storage_class = "GLACIER"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Clean up incomplete multipart uploads
|
|
118
|
+
rule {
|
|
119
|
+
id = "cleanup-multipart"
|
|
120
|
+
status = "Enabled"
|
|
121
|
+
|
|
122
|
+
filter {}
|
|
123
|
+
|
|
124
|
+
abort_incomplete_multipart_upload {
|
|
125
|
+
days_after_initiation = 7
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
# --- IAM Policy ---
|
|
131
|
+
|
|
132
|
+
# IAM policy document scoped to Fractary prefixes only
|
|
133
|
+
data "aws_iam_policy_document" "fractary_access" {
|
|
134
|
+
statement {
|
|
135
|
+
sid = "FractaryListBucket"
|
|
136
|
+
effect = "Allow"
|
|
137
|
+
|
|
138
|
+
actions = [
|
|
139
|
+
"s3:ListBucket",
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
resources = [
|
|
143
|
+
aws_s3_bucket.fractary.arn,
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
condition {
|
|
147
|
+
test = "StringLike"
|
|
148
|
+
variable = "s3:prefix"
|
|
149
|
+
values = [
|
|
150
|
+
"logs/*",
|
|
151
|
+
"docs/*",
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
statement {
|
|
157
|
+
sid = "FractaryObjectAccess"
|
|
158
|
+
effect = "Allow"
|
|
159
|
+
|
|
160
|
+
actions = [
|
|
161
|
+
"s3:GetObject",
|
|
162
|
+
"s3:PutObject",
|
|
163
|
+
"s3:DeleteObject",
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
resources = [
|
|
167
|
+
"${aws_s3_bucket.fractary.arn}/logs/*",
|
|
168
|
+
"${aws_s3_bucket.fractary.arn}/docs/*",
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
resource "aws_iam_policy" "fractary_access" {
|
|
174
|
+
name = "fractary-${var.project_name}-storage-access"
|
|
175
|
+
description = "Scoped access to Fractary storage bucket for ${var.project_name}"
|
|
176
|
+
policy = data.aws_iam_policy_document.fractary_access.json
|
|
177
|
+
|
|
178
|
+
tags = {
|
|
179
|
+
ManagedBy = "fractary-core"
|
|
180
|
+
Project = var.project_name
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# --- Outputs ---
|
|
185
|
+
|
|
186
|
+
output "bucket_name" {
|
|
187
|
+
description = "The name of the Fractary S3 bucket"
|
|
188
|
+
value = aws_s3_bucket.fractary.bucket
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
output "bucket_arn" {
|
|
192
|
+
description = "The ARN of the Fractary S3 bucket"
|
|
193
|
+
value = aws_s3_bucket.fractary.arn
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
output "bucket_region" {
|
|
197
|
+
description = "The region of the Fractary S3 bucket"
|
|
198
|
+
value = aws_s3_bucket.fractary.region
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
output "iam_policy_arn" {
|
|
202
|
+
description = "The ARN of the IAM policy for Fractary bucket access"
|
|
203
|
+
value = aws_iam_policy.fractary_access.arn
|
|
204
|
+
}
|