@s-gw/s-gw 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/.codex-plugin/plugin.json +35 -0
  2. package/.mcp.json +16 -0
  3. package/LICENSE +201 -0
  4. package/NOTICE +7 -0
  5. package/README.md +197 -0
  6. package/TRADEMARKS.md +9 -0
  7. package/assets/icons/aws-ec2.png +0 -0
  8. package/assets/icons/lucide/bot.svg +8 -0
  9. package/assets/icons/lucide/monitor.svg +5 -0
  10. package/assets/icons/lucide/server.svg +6 -0
  11. package/assets/icons/lucide/terminal.svg +4 -0
  12. package/assets/icons/s-gw-128.png +0 -0
  13. package/assets/icons/s-gw-16.png +0 -0
  14. package/assets/icons/s-gw-180.png +0 -0
  15. package/assets/icons/s-gw-192.png +0 -0
  16. package/assets/icons/s-gw-32.png +0 -0
  17. package/assets/icons/s-gw-64.png +0 -0
  18. package/assets/icons/s-gw-menu-bar-template.png +0 -0
  19. package/dist/agent-context.d.ts +17 -0
  20. package/dist/agent-context.js +207 -0
  21. package/dist/agents.d.ts +64 -0
  22. package/dist/agents.js +763 -0
  23. package/dist/cli.d.ts +2 -0
  24. package/dist/cli.js +1385 -0
  25. package/dist/command-suggest.d.ts +3 -0
  26. package/dist/command-suggest.js +131 -0
  27. package/dist/console-server.d.ts +16 -0
  28. package/dist/console-server.js +978 -0
  29. package/dist/console-ui/assets/codex-DYTPdPxi.png +0 -0
  30. package/dist/console-ui/assets/cursor-CBrUTJD-.png +0 -0
  31. package/dist/console-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  32. package/dist/console-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  33. package/dist/console-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  34. package/dist/console-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  35. package/dist/console-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  36. package/dist/console-ui/assets/hermes-B8hNbJPm.png +0 -0
  37. package/dist/console-ui/assets/index-BxUf0Sye.js +96 -0
  38. package/dist/console-ui/assets/index-CmTiBR_w.css +2 -0
  39. package/dist/console-ui/assets/omnigent-Cxa4p2Mq.png +0 -0
  40. package/dist/console-ui/assets/openclaw-C5wL4ZVW.png +0 -0
  41. package/dist/console-ui/assets/opencode-D_wFATSC.png +0 -0
  42. package/dist/console-ui/assets/openhands-DnrlGgev.svg +9 -0
  43. package/dist/console-ui/assets/s-gw-64-ByMUGQ3K.png +0 -0
  44. package/dist/console-ui/assets/vscode-Bdtr9eyf.png +0 -0
  45. package/dist/console-ui/assets/zeptoclaw-DztQW8Sw.png +0 -0
  46. package/dist/console-ui/index.html +13 -0
  47. package/dist/crypto.d.ts +6 -0
  48. package/dist/crypto.js +53 -0
  49. package/dist/executor.d.ts +7 -0
  50. package/dist/executor.js +297 -0
  51. package/dist/gateway.d.ts +31 -0
  52. package/dist/gateway.js +114 -0
  53. package/dist/guard.d.ts +61 -0
  54. package/dist/guard.js +247 -0
  55. package/dist/install.d.ts +146 -0
  56. package/dist/install.js +629 -0
  57. package/dist/mcp-server.d.ts +2 -0
  58. package/dist/mcp-server.js +119 -0
  59. package/dist/native/s-gw-core +0 -0
  60. package/dist/native/s-gw-keychain-helper +0 -0
  61. package/dist/onepassword.d.ts +48 -0
  62. package/dist/onepassword.js +412 -0
  63. package/dist/paths.d.ts +4 -0
  64. package/dist/paths.js +22 -0
  65. package/dist/s-gw Menu Bar.app/Contents/Info.plist +28 -0
  66. package/dist/s-gw Menu Bar.app/Contents/MacOS/s-gw-menu-bar-helper +0 -0
  67. package/dist/s-gw Menu Bar.app/Contents/Resources/AppIcon.icns +0 -0
  68. package/dist/s-gw Menu Bar.app/Contents/Resources/AwsEc2.png +0 -0
  69. package/dist/s-gw Menu Bar.app/Contents/Resources/Lucide-bot.svg +8 -0
  70. package/dist/s-gw Menu Bar.app/Contents/Resources/Lucide-monitor.svg +5 -0
  71. package/dist/s-gw Menu Bar.app/Contents/Resources/Lucide-server.svg +6 -0
  72. package/dist/s-gw Menu Bar.app/Contents/Resources/Lucide-terminal.svg +4 -0
  73. package/dist/s-gw Menu Bar.app/Contents/Resources/MenuBarTemplate.png +0 -0
  74. package/dist/s-gw Menu Bar.app/Contents/_CodeSignature/CodeResources +194 -0
  75. package/dist/s-gw.app/Contents/Info.plist +28 -0
  76. package/dist/s-gw.app/Contents/MacOS/s-gw +0 -0
  77. package/dist/s-gw.app/Contents/Resources/AppIcon.icns +0 -0
  78. package/dist/s-gw.app/Contents/Resources/MenuBarTemplate.png +0 -0
  79. package/dist/s-gw.app/Contents/_CodeSignature/CodeResources +139 -0
  80. package/dist/scanner.d.ts +9 -0
  81. package/dist/scanner.js +437 -0
  82. package/dist/ssh.d.ts +31 -0
  83. package/dist/ssh.js +286 -0
  84. package/dist/store.d.ts +131 -0
  85. package/dist/store.js +1611 -0
  86. package/dist/types.d.ts +196 -0
  87. package/dist/types.js +2 -0
  88. package/dist/unlock.d.ts +29 -0
  89. package/dist/unlock.js +274 -0
  90. package/dist/windows/VERSION.txt +1 -0
  91. package/dist/windows/s-gw-client.cmd +4 -0
  92. package/dist/windows/s-gw-client.ps1 +106 -0
  93. package/dist/windows/s-gw-credential.cmd +4 -0
  94. package/dist/windows/s-gw-credential.ps1 +167 -0
  95. package/dist/windows/s-gw-helper.cmd +4 -0
  96. package/dist/windows/s-gw-helper.ps1 +180 -0
  97. package/docs/README.md +23 -0
  98. package/docs/agents.md +160 -0
  99. package/docs/architecture.md +72 -0
  100. package/docs/deployment.md +447 -0
  101. package/docs/detection.md +44 -0
  102. package/docs/images/s-gw-overview.png +0 -0
  103. package/docs/integrations.md +195 -0
  104. package/docs/keychain.md +39 -0
  105. package/docs/onepassword.md +84 -0
  106. package/docs/quickstart.md +104 -0
  107. package/docs/threat-model.md +100 -0
  108. package/docs/ui/THIRD_PARTY_NOTICES.md +111 -0
  109. package/docs/ui/apple-touch-icon.png +0 -0
  110. package/docs/ui/favicon-32.png +0 -0
  111. package/docs/ui/local-console.html +4477 -0
  112. package/docs/ui/vendor/d3-sankey/d3-array.LICENSE.txt +27 -0
  113. package/docs/ui/vendor/d3-sankey/d3-array.min.js +2 -0
  114. package/docs/ui/vendor/d3-sankey/d3-path.LICENSE.txt +27 -0
  115. package/docs/ui/vendor/d3-sankey/d3-path.min.js +2 -0
  116. package/docs/ui/vendor/d3-sankey/d3-sankey.LICENSE.txt +27 -0
  117. package/docs/ui/vendor/d3-sankey/d3-sankey.min.js +2 -0
  118. package/docs/ui/vendor/d3-sankey/d3-shape.LICENSE.txt +27 -0
  119. package/docs/ui/vendor/d3-sankey/d3-shape.min.js +2 -0
  120. package/docs/ui/vendor/sankeymatic/LICENSE.txt +17 -0
  121. package/docs/ui/vendor/sankeymatic/sankey.js +897 -0
  122. package/package.json +117 -0
  123. package/skills/s-gw/SKILL.md +19 -0
@@ -0,0 +1,196 @@
1
+ export type SecretType = "api-token" | "ssh-key" | "private-key" | "password" | "credential" | "access-key" | "unknown";
2
+ export type SecretSeverity = "low" | "medium" | "high" | "critical";
3
+ export type RequestState = "pending" | "approved" | "executing" | "denied" | "executed" | "failed";
4
+ export type ApprovalMode = "per-transaction" | "timed-session" | "login-session" | "always";
5
+ export type ApprovalAgentScope = "same-agent" | "any-agent";
6
+ export type ApprovalPolicyDecision = "ask" | "allow" | "deny";
7
+ export type ApprovalPolicyActionKind = "env_command" | "ssh_session";
8
+ export type AgentIdentitySource = "configured" | "mcp-client" | "runtime" | "process" | "reason" | "manual" | "unknown";
9
+ export interface ApprovalSettings {
10
+ mode: ApprovalMode;
11
+ durationMs: number;
12
+ }
13
+ export interface ApprovalGrant {
14
+ id: string;
15
+ handle: string;
16
+ actionKey: string;
17
+ mode: Exclude<ApprovalMode, "per-transaction">;
18
+ agentScope?: ApprovalAgentScope;
19
+ agentName?: string;
20
+ loginSessionId: string;
21
+ createdAt: string;
22
+ updatedAt: string;
23
+ expiresAt?: string;
24
+ lastRequestId?: string;
25
+ }
26
+ export interface ApprovalPolicyConditions {
27
+ handles?: string[];
28
+ secretTypes?: SecretType[];
29
+ providers?: string[];
30
+ minSeverity?: SecretSeverity;
31
+ agents?: string[];
32
+ actionKinds?: ApprovalPolicyActionKind[];
33
+ commands?: string[];
34
+ injectEnvs?: string[];
35
+ workingDirs?: string[];
36
+ sshTargets?: string[];
37
+ sshPorts?: number[];
38
+ }
39
+ export interface ApprovalPolicyRule {
40
+ id: string;
41
+ name: string;
42
+ enabled: boolean;
43
+ priority: number;
44
+ decision: ApprovalPolicyDecision;
45
+ conditions: ApprovalPolicyConditions;
46
+ expiresAt?: string;
47
+ createdAt: string;
48
+ updatedAt: string;
49
+ }
50
+ export interface EncryptedBox {
51
+ alg: "aes-256-gcm";
52
+ kdf: "scrypt";
53
+ salt: string;
54
+ iv: string;
55
+ authTag: string;
56
+ ciphertext: string;
57
+ }
58
+ export interface SecretPolicy {
59
+ injectEnv?: string;
60
+ allowedCommands: string[];
61
+ maxOutputBytes: number;
62
+ }
63
+ export type SecretBackend = "local" | "onepassword" | "keychain";
64
+ export interface SecretValueCache {
65
+ backend: "onepassword";
66
+ encrypted: EncryptedBox;
67
+ fingerprint: string;
68
+ approvalGrantId: string;
69
+ createdAt: string;
70
+ updatedAt: string;
71
+ expiresAt?: string;
72
+ loginSessionId?: string;
73
+ }
74
+ export interface SecretRecord {
75
+ handle: string;
76
+ name: string;
77
+ type: SecretType;
78
+ backend?: SecretBackend;
79
+ provider?: string;
80
+ ruleId?: string;
81
+ severity?: SecretSeverity;
82
+ confidence?: number;
83
+ createdAt: string;
84
+ updatedAt: string;
85
+ source?: string;
86
+ fingerprint: string;
87
+ encrypted: EncryptedBox;
88
+ cache?: SecretValueCache;
89
+ policy: SecretPolicy;
90
+ }
91
+ export interface HandleSummary {
92
+ handle: string;
93
+ name: string;
94
+ type: SecretType;
95
+ backend?: SecretBackend;
96
+ provider?: string;
97
+ ruleId?: string;
98
+ severity?: SecretSeverity;
99
+ confidence?: number;
100
+ createdAt: string;
101
+ updatedAt: string;
102
+ source?: string;
103
+ fingerprint: string;
104
+ policy: SecretPolicy;
105
+ }
106
+ export interface SshSessionSpec {
107
+ target: string;
108
+ port: number;
109
+ }
110
+ export interface CommandEnvBinding {
111
+ handle: string;
112
+ injectEnv: string;
113
+ }
114
+ export interface CommandAction {
115
+ kind: "env_command" | "ssh_session";
116
+ command: string;
117
+ args: string[];
118
+ injectEnv: string;
119
+ env?: CommandEnvBinding[];
120
+ workingDir?: string;
121
+ timeoutMs: number;
122
+ ssh?: SshSessionSpec;
123
+ }
124
+ export interface ExecutionSummary {
125
+ exitCode: number | null;
126
+ signal: NodeJS.Signals | null;
127
+ stdout: string;
128
+ stderr: string;
129
+ proof: string;
130
+ durationMs: number;
131
+ timeoutMs: number;
132
+ timedOut: boolean;
133
+ sanitized: boolean;
134
+ }
135
+ export interface RequestRecord {
136
+ id: string;
137
+ handle: string;
138
+ reason: string;
139
+ agentName?: string;
140
+ agentSource?: AgentIdentitySource;
141
+ action: CommandAction;
142
+ state: RequestState;
143
+ createdAt: string;
144
+ updatedAt: string;
145
+ approvedAt?: string;
146
+ approvalGrantId?: string;
147
+ approvalPolicyRuleId?: string;
148
+ deniedAt?: string;
149
+ executedAt?: string;
150
+ resultSummary?: ExecutionSummary;
151
+ error?: string;
152
+ }
153
+ export interface AuditEvent {
154
+ id: string;
155
+ ts: string;
156
+ type: string;
157
+ handle?: string;
158
+ requestId?: string;
159
+ message: string;
160
+ }
161
+ export interface StoreFile {
162
+ version: 1;
163
+ secrets: SecretRecord[];
164
+ requests: RequestRecord[];
165
+ audit: AuditEvent[];
166
+ approvalSettings: ApprovalSettings;
167
+ approvalGrants: ApprovalGrant[];
168
+ approvalPolicyRules: ApprovalPolicyRule[];
169
+ }
170
+ export interface ScanCandidate {
171
+ type: SecretType;
172
+ label: string;
173
+ provider?: string;
174
+ ruleId?: string;
175
+ severity?: SecretSeverity;
176
+ confidence?: number;
177
+ value: string;
178
+ start: number;
179
+ end: number;
180
+ }
181
+ export interface ScanFinding {
182
+ type: SecretType;
183
+ label: string;
184
+ provider?: string;
185
+ ruleId?: string;
186
+ severity?: SecretSeverity;
187
+ confidence?: number;
188
+ handle: string;
189
+ token: string;
190
+ start: number;
191
+ end: number;
192
+ }
193
+ export interface ScanResult {
194
+ tokenizedText: string;
195
+ findings: ScanFinding[];
196
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,29 @@
1
+ export interface KeychainInfo {
2
+ supported: boolean;
3
+ service: string;
4
+ account: string;
5
+ provider: "native-helper" | "security-cli" | "windows-helper" | "none";
6
+ helperPath?: string;
7
+ }
8
+ export interface UnlockStatus {
9
+ envConfigured: boolean;
10
+ activeSource: "env" | "macos-keychain" | "windows-credential-manager" | "none";
11
+ keychain: KeychainInfo & {
12
+ configured: boolean;
13
+ };
14
+ }
15
+ export interface MacKeychainItemRef {
16
+ service: string;
17
+ account: string;
18
+ label?: string;
19
+ }
20
+ export declare function requireUnlockPassphrase(): string;
21
+ export declare function unlockStatus(): UnlockStatus;
22
+ export declare function setKeychainPassphrase(passphrase: string): void;
23
+ export declare function deleteKeychainPassphrase(): boolean;
24
+ export declare function hasKeychainPassphrase(): boolean;
25
+ export declare function keychainInfo(): KeychainInfo;
26
+ export declare function defaultSecretKeychainService(): string;
27
+ export declare function setMacKeychainItem(ref: MacKeychainItemRef, value: string): void;
28
+ export declare function getMacKeychainItem(ref: MacKeychainItemRef): string;
29
+ export declare function deleteMacKeychainItem(ref: MacKeychainItemRef): boolean;
package/dist/unlock.js ADDED
@@ -0,0 +1,274 @@
1
+ import { execFileSync, spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ const defaultService = "com.s-gw.sgw.master-passphrase";
7
+ const defaultSecretService = "com.s-gw.sgw.secret";
8
+ const nativeHelperName = "s-gw-keychain-helper";
9
+ const windowsCredentialHelperName = "s-gw-credential.ps1";
10
+ export function requireUnlockPassphrase() {
11
+ const fromEnv = process.env.SGW_MASTER_PASSPHRASE;
12
+ if (validPassphrase(fromEnv)) {
13
+ return fromEnv;
14
+ }
15
+ const fromKeychain = readKeychainPassphrase();
16
+ if (validPassphrase(fromKeychain)) {
17
+ return fromKeychain;
18
+ }
19
+ throw new Error("s-gw needs a local unlock passphrase. Run `s-gw unlock keychain set --value-stdin` or set SGW_MASTER_PASSPHRASE.");
20
+ }
21
+ export function unlockStatus() {
22
+ const envConfigured = validPassphrase(process.env.SGW_MASTER_PASSPHRASE);
23
+ const keychain = keychainInfo();
24
+ const configured = hasKeychainPassphrase();
25
+ let activeSource = "none";
26
+ if (envConfigured) {
27
+ activeSource = "env";
28
+ }
29
+ else if (configured) {
30
+ activeSource = process.platform === "win32" ? "windows-credential-manager" : "macos-keychain";
31
+ }
32
+ return {
33
+ envConfigured,
34
+ activeSource,
35
+ keychain: {
36
+ ...keychain,
37
+ configured
38
+ }
39
+ };
40
+ }
41
+ export function setKeychainPassphrase(passphrase) {
42
+ if (!validPassphrase(passphrase)) {
43
+ throw new Error("Unlock passphrase must be at least 8 characters.");
44
+ }
45
+ ensureLocalCredentialStore();
46
+ runKeychainSet(keychainInfo(), passphrase);
47
+ }
48
+ export function deleteKeychainPassphrase() {
49
+ ensureLocalCredentialStore();
50
+ try {
51
+ runKeychainDelete(keychainInfo());
52
+ return true;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ export function hasKeychainPassphrase() {
59
+ if (!keychainInfo().supported || process.env.SGW_DISABLE_KEYCHAIN === "1") {
60
+ return false;
61
+ }
62
+ const passphrase = readKeychainPassphrase();
63
+ return validPassphrase(passphrase);
64
+ }
65
+ export function keychainInfo() {
66
+ return {
67
+ supported: supportsLocalCredentialStore(),
68
+ service: process.env.SGW_KEYCHAIN_SERVICE || defaultService,
69
+ account: process.env.SGW_KEYCHAIN_ACCOUNT || os.userInfo().username || "local-user",
70
+ ...keychainProvider()
71
+ };
72
+ }
73
+ export function defaultSecretKeychainService() {
74
+ return process.env.SGW_SECRET_KEYCHAIN_SERVICE || defaultSecretService;
75
+ }
76
+ export function setMacKeychainItem(ref, value) {
77
+ if (!value) {
78
+ throw new Error("Cannot store an empty Keychain item.");
79
+ }
80
+ const info = keychainInfoForItem(ref);
81
+ ensureNativeCredentialStore(info);
82
+ runKeychainSet(info, value, ref.label || "s-gw local secret");
83
+ }
84
+ export function getMacKeychainItem(ref) {
85
+ const info = keychainInfoForItem(ref);
86
+ ensureNativeCredentialStore(info);
87
+ return runKeychainGet(info).replace(/\r?\n$/, "");
88
+ }
89
+ export function deleteMacKeychainItem(ref) {
90
+ try {
91
+ const info = keychainInfoForItem(ref);
92
+ ensureNativeCredentialStore(info);
93
+ runKeychainDelete(info);
94
+ return true;
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ }
100
+ function readKeychainPassphrase() {
101
+ const info = keychainInfo();
102
+ if (!info.supported || process.env.SGW_DISABLE_KEYCHAIN === "1") {
103
+ return undefined;
104
+ }
105
+ try {
106
+ const output = runKeychainGet(info);
107
+ return output.replace(/\r?\n$/, "");
108
+ }
109
+ catch {
110
+ return undefined;
111
+ }
112
+ }
113
+ function ensureLocalCredentialStore() {
114
+ if (!keychainInfo().supported) {
115
+ throw new Error("OS credential-store unlock is only available on macOS or Windows.");
116
+ }
117
+ }
118
+ function ensureNativeCredentialStore(info) {
119
+ if (!info.supported) {
120
+ throw new Error("OS credential-store secret storage is only available on macOS or Windows.");
121
+ }
122
+ if ((info.provider !== "native-helper" && info.provider !== "windows-helper") || !info.helperPath) {
123
+ throw new Error("OS credential-store secret storage requires the native s-gw helper. Run `npm run build:native`.");
124
+ }
125
+ }
126
+ function keychainInfoForItem(ref) {
127
+ const service = ref.service.trim();
128
+ const account = ref.account.trim();
129
+ if (!service || !account) {
130
+ throw new Error("Keychain service and account are required.");
131
+ }
132
+ return {
133
+ supported: supportsLocalCredentialStore(),
134
+ service,
135
+ account,
136
+ ...keychainProvider()
137
+ };
138
+ }
139
+ function validPassphrase(value) {
140
+ return typeof value === "string" && value.trim().length >= 8;
141
+ }
142
+ function keychainProvider() {
143
+ if (process.platform === "win32") {
144
+ const helperPath = findWindowsCredentialHelper();
145
+ return helperPath ? { provider: "windows-helper", helperPath } : { provider: "none" };
146
+ }
147
+ if (process.platform !== "darwin") {
148
+ return { provider: "none" };
149
+ }
150
+ const helperPath = findNativeHelper();
151
+ if (helperPath) {
152
+ return { provider: "native-helper", helperPath };
153
+ }
154
+ if (process.env.SGW_ALLOW_SECURITY_CLI === "1") {
155
+ return { provider: "security-cli" };
156
+ }
157
+ return { provider: "none" };
158
+ }
159
+ function supportsLocalCredentialStore() {
160
+ return process.platform === "darwin" || process.platform === "win32";
161
+ }
162
+ function findNativeHelper() {
163
+ const fromEnv = process.env.SGW_KEYCHAIN_HELPER;
164
+ if (fromEnv && existsSync(fromEnv)) {
165
+ return fromEnv;
166
+ }
167
+ const here = path.dirname(fileURLToPath(import.meta.url));
168
+ const candidates = [
169
+ path.resolve(here, "native", nativeHelperName),
170
+ path.resolve(process.cwd(), "dist", "native", nativeHelperName)
171
+ ];
172
+ return candidates.find((candidate) => existsSync(candidate));
173
+ }
174
+ function findWindowsCredentialHelper() {
175
+ const fromEnv = process.env.SGW_WINDOWS_CREDENTIAL_HELPER || process.env.SGW_KEYCHAIN_HELPER;
176
+ if (fromEnv && existsSync(fromEnv)) {
177
+ return fromEnv;
178
+ }
179
+ const here = path.dirname(fileURLToPath(import.meta.url));
180
+ const candidates = [
181
+ path.resolve(here, "windows", windowsCredentialHelperName),
182
+ path.resolve(process.cwd(), "dist", "windows", windowsCredentialHelperName)
183
+ ];
184
+ return candidates.find((candidate) => existsSync(candidate));
185
+ }
186
+ function runKeychainGet(info) {
187
+ if (info.provider === "native-helper" && info.helperPath) {
188
+ return runNativeHelper(info.helperPath, ["get", "--service", info.service, "--account", info.account]);
189
+ }
190
+ if (info.provider === "security-cli") {
191
+ return runSecurity([
192
+ "find-generic-password",
193
+ "-a",
194
+ info.account,
195
+ "-s",
196
+ info.service,
197
+ "-w"
198
+ ]);
199
+ }
200
+ if (info.provider === "windows-helper" && info.helperPath) {
201
+ return runWindowsCredentialHelper(info.helperPath, ["get", "-Service", info.service, "-Account", info.account]);
202
+ }
203
+ throw new Error("No local OS credential-store provider is available. Run `npm run build:native`.");
204
+ }
205
+ function runKeychainSet(info, passphrase, label = "s-gw local unlock passphrase") {
206
+ if (info.provider === "native-helper" && info.helperPath) {
207
+ runNativeHelper(info.helperPath, ["set", "--service", info.service, "--account", info.account, "--label", label], passphrase);
208
+ return;
209
+ }
210
+ if (info.provider === "security-cli") {
211
+ runSecurity([
212
+ "add-generic-password",
213
+ "-U",
214
+ "-a",
215
+ info.account,
216
+ "-s",
217
+ info.service,
218
+ "-l",
219
+ label,
220
+ "-w",
221
+ passphrase
222
+ ]);
223
+ return;
224
+ }
225
+ if (info.provider === "windows-helper" && info.helperPath) {
226
+ runWindowsCredentialHelper(info.helperPath, ["set", "-Service", info.service, "-Account", info.account, "-Label", label], passphrase);
227
+ return;
228
+ }
229
+ throw new Error("No local OS credential-store provider is available. Run `npm run build:native`.");
230
+ }
231
+ function runKeychainDelete(info) {
232
+ if (info.provider === "native-helper" && info.helperPath) {
233
+ runNativeHelper(info.helperPath, ["delete", "--service", info.service, "--account", info.account]);
234
+ return;
235
+ }
236
+ if (info.provider === "security-cli") {
237
+ runSecurity(["delete-generic-password", "-a", info.account, "-s", info.service]);
238
+ return;
239
+ }
240
+ if (info.provider === "windows-helper" && info.helperPath) {
241
+ runWindowsCredentialHelper(info.helperPath, ["delete", "-Service", info.service, "-Account", info.account]);
242
+ return;
243
+ }
244
+ throw new Error("No local OS credential-store provider is available. Run `npm run build:native`.");
245
+ }
246
+ function runNativeHelper(helperPath, args, input) {
247
+ const result = spawnSync(helperPath, args, {
248
+ input,
249
+ encoding: "utf8",
250
+ stdio: ["pipe", "pipe", "pipe"]
251
+ });
252
+ if (result.status !== 0) {
253
+ throw new Error(result.stderr.trim() || `Native Keychain helper failed with status ${result.status}`);
254
+ }
255
+ return result.stdout;
256
+ }
257
+ function runSecurity(args) {
258
+ return execFileSync("security", args, {
259
+ encoding: "utf8",
260
+ stdio: ["ignore", "pipe", "pipe"]
261
+ });
262
+ }
263
+ function runWindowsCredentialHelper(helperPath, args, input) {
264
+ const result = spawnSync("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", helperPath, ...args], {
265
+ input,
266
+ encoding: "utf8",
267
+ stdio: ["pipe", "pipe", "pipe"]
268
+ });
269
+ if (result.status !== 0) {
270
+ throw new Error(result.stderr.trim() || `Windows Credential Manager helper failed with status ${result.status}`);
271
+ }
272
+ return result.stdout;
273
+ }
274
+ //# sourceMappingURL=unlock.js.map
@@ -0,0 +1 @@
1
+ s-gw 0.1.0
@@ -0,0 +1,4 @@
1
+ @echo off
2
+ setlocal
3
+ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0s-gw-client.ps1" %*
4
+ exit /b %ERRORLEVEL%
@@ -0,0 +1,106 @@
1
+ [CmdletBinding()]
2
+ param(
3
+ [int]$Port = 8718,
4
+ [string]$ConsoleUrl = "",
5
+ [switch]$NoStart
6
+ )
7
+
8
+ $ErrorActionPreference = "Stop"
9
+
10
+ function Resolve-CliPath {
11
+ if ($env:SGW_CLI_PATH -and (Test-Path -LiteralPath $env:SGW_CLI_PATH)) {
12
+ return (Resolve-Path -LiteralPath $env:SGW_CLI_PATH).Path
13
+ }
14
+
15
+ $distDir = Split-Path -Parent $PSScriptRoot
16
+ $candidate = Join-Path $distDir "cli.js"
17
+ if (Test-Path -LiteralPath $candidate) {
18
+ return (Resolve-Path -LiteralPath $candidate).Path
19
+ }
20
+
21
+ throw "Unable to find s-gw CLI. Set SGW_CLI_PATH to dist\cli.js."
22
+ }
23
+
24
+ function Resolve-NodePath {
25
+ if ($env:SGW_NODE_PATH) {
26
+ return $env:SGW_NODE_PATH
27
+ }
28
+ return "node"
29
+ }
30
+
31
+ function New-ConsoleUrl {
32
+ if ($ConsoleUrl.Trim()) {
33
+ return $ConsoleUrl.Trim()
34
+ }
35
+ return "http://127.0.0.1:$Port/"
36
+ }
37
+
38
+ function Get-OriginUrl([string]$Url) {
39
+ $uri = [Uri]$Url
40
+ return $uri.GetLeftPart([UriPartial]::Authority) + "/"
41
+ }
42
+
43
+ function Test-ConsoleReady([string]$Url) {
44
+ $origin = Get-OriginUrl $Url
45
+ try {
46
+ $health = Invoke-RestMethod -Method Get -Uri ($origin + "api/health") -TimeoutSec 1
47
+ return ($health.ok -eq $true)
48
+ } catch {
49
+ return $false
50
+ }
51
+ }
52
+
53
+ function Start-ConsoleDaemon([string]$CliPath, [string]$NodePath) {
54
+ $logs = Join-Path $env:LOCALAPPDATA "s-gw\logs"
55
+ New-Item -ItemType Directory -Force -Path $logs | Out-Null
56
+
57
+ $args = @($CliPath, "console", "--host", "127.0.0.1", "--port", [string]$Port, "--no-open")
58
+ $root = Split-Path -Parent (Split-Path -Parent $CliPath)
59
+
60
+ Start-Process `
61
+ -FilePath $NodePath `
62
+ -ArgumentList $args `
63
+ -WorkingDirectory $root `
64
+ -WindowStyle Hidden `
65
+ -RedirectStandardOutput (Join-Path $logs "console.log") `
66
+ -RedirectStandardError (Join-Path $logs "console.err.log") | Out-Null
67
+ }
68
+
69
+ function Wait-Console([string]$Url) {
70
+ for ($i = 0; $i -lt 30; $i += 1) {
71
+ if (Test-ConsoleReady $Url) {
72
+ return $true
73
+ }
74
+ Start-Sleep -Milliseconds 250
75
+ }
76
+ return $false
77
+ }
78
+
79
+ function Open-ConsoleWindow([string]$Url) {
80
+ $edge = Get-Command "msedge.exe" -ErrorAction SilentlyContinue
81
+ if ($edge) {
82
+ Start-Process -FilePath $edge.Source -ArgumentList @("--app=$Url") | Out-Null
83
+ return
84
+ }
85
+
86
+ $chrome = Get-Command "chrome.exe" -ErrorAction SilentlyContinue
87
+ if ($chrome) {
88
+ Start-Process -FilePath $chrome.Source -ArgumentList @("--app=$Url") | Out-Null
89
+ return
90
+ }
91
+
92
+ Start-Process $Url | Out-Null
93
+ }
94
+
95
+ $url = New-ConsoleUrl
96
+ $cliPath = Resolve-CliPath
97
+ $nodePath = Resolve-NodePath
98
+
99
+ if (-not $NoStart -and -not (Test-ConsoleReady $url)) {
100
+ Start-ConsoleDaemon -CliPath $cliPath -NodePath $nodePath
101
+ if (-not (Wait-Console $url)) {
102
+ throw "s-gw console did not become ready at $url. Check $env:LOCALAPPDATA\s-gw\logs."
103
+ }
104
+ }
105
+
106
+ Open-ConsoleWindow $url
@@ -0,0 +1,4 @@
1
+ @echo off
2
+ setlocal
3
+ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0s-gw-credential.ps1" %*
4
+ exit /b %ERRORLEVEL%