@linkup-ai/abap-ai 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 (119) hide show
  1. package/README.md +389 -0
  2. package/dist/adt-client.js +383 -0
  3. package/dist/cli/activate.js +127 -0
  4. package/dist/cli/init.js +559 -0
  5. package/dist/cli/link.js +148 -0
  6. package/dist/cli/remove.js +83 -0
  7. package/dist/cli/status.js +231 -0
  8. package/dist/cli/systems.js +72 -0
  9. package/dist/cli.js +92 -0
  10. package/dist/index.js +1442 -0
  11. package/dist/knowledge/abap/abap-dictionary.md +199 -0
  12. package/dist/knowledge/abap/abap-sql.md +296 -0
  13. package/dist/knowledge/abap/amdp.md +273 -0
  14. package/dist/knowledge/abap/clean-code.md +293 -0
  15. package/dist/knowledge/abap/cloud-background-processing.md +250 -0
  16. package/dist/knowledge/abap/cloud-communication.md +265 -0
  17. package/dist/knowledge/abap/cloud-development.md +176 -0
  18. package/dist/knowledge/abap/cloud-extensibility.md +252 -0
  19. package/dist/knowledge/abap/cloud-released-apis.md +261 -0
  20. package/dist/knowledge/abap/constructor-expressions.md +289 -0
  21. package/dist/knowledge/abap/enhancements.md +232 -0
  22. package/dist/knowledge/abap/exceptions.md +271 -0
  23. package/dist/knowledge/abap/internal-tables.md +205 -0
  24. package/dist/knowledge/abap/object-orientation.md +298 -0
  25. package/dist/knowledge/abap/performance.md +216 -0
  26. package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
  27. package/dist/knowledge/abap/rap-business-events.md +216 -0
  28. package/dist/knowledge/abap/rap-draft.md +191 -0
  29. package/dist/knowledge/abap/rap-eml.md +453 -0
  30. package/dist/knowledge/abap/rap-end-to-end.md +486 -0
  31. package/dist/knowledge/abap/rap-feature-control.md +185 -0
  32. package/dist/knowledge/abap/rap-numbering.md +280 -0
  33. package/dist/knowledge/abap/rap-service-exposure.md +163 -0
  34. package/dist/knowledge/abap/rap-unmanaged.md +468 -0
  35. package/dist/knowledge/abap/string-processing.md +180 -0
  36. package/dist/knowledge/abap/unit-testing.md +303 -0
  37. package/dist/knowledge/abap-cds/access-control.md +241 -0
  38. package/dist/knowledge/abap-cds/annotations.md +331 -0
  39. package/dist/knowledge/abap-cds/associations.md +254 -0
  40. package/dist/knowledge/abap-cds/expressions.md +230 -0
  41. package/dist/knowledge/abap-cds/functions.md +245 -0
  42. package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
  43. package/dist/knowledge/cap/authentication.md +278 -0
  44. package/dist/knowledge/cap/cdl-syntax.md +247 -0
  45. package/dist/knowledge/cap/cql-queries.md +266 -0
  46. package/dist/knowledge/cap/deployment.md +343 -0
  47. package/dist/knowledge/cap/event-handlers.md +287 -0
  48. package/dist/knowledge/cap/fiori-integration.md +303 -0
  49. package/dist/knowledge/cap/service-definitions.md +287 -0
  50. package/dist/knowledge/fiori/annotations.md +347 -0
  51. package/dist/knowledge/fiori/deployment.md +340 -0
  52. package/dist/knowledge/fiori/fiori-elements.md +332 -0
  53. package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
  54. package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
  55. package/dist/knowledge/fiori/ui5-controllers.md +358 -0
  56. package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
  57. package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
  58. package/dist/knowledge/fiori/ui5-manifest.md +411 -0
  59. package/dist/knowledge/fiori/ui5-routing.md +303 -0
  60. package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
  61. package/dist/license-guard.js +81 -0
  62. package/dist/logger.js +114 -0
  63. package/dist/postinstall.js +165 -0
  64. package/dist/security-audit.js +136 -0
  65. package/dist/security-policy.js +322 -0
  66. package/dist/system-profile.js +207 -0
  67. package/dist/tools/abap-doc.js +72 -0
  68. package/dist/tools/abapgit.js +161 -0
  69. package/dist/tools/activate.js +71 -0
  70. package/dist/tools/atc-check.js +117 -0
  71. package/dist/tools/auth-object.js +56 -0
  72. package/dist/tools/breakpoints.js +76 -0
  73. package/dist/tools/call-hierarchy.js +84 -0
  74. package/dist/tools/cds-annotations.js +98 -0
  75. package/dist/tools/cds-dependencies.js +65 -0
  76. package/dist/tools/check.js +47 -0
  77. package/dist/tools/code-completion.js +70 -0
  78. package/dist/tools/code-coverage.js +111 -0
  79. package/dist/tools/create-amdp.js +111 -0
  80. package/dist/tools/create-dcl.js +81 -0
  81. package/dist/tools/create-transport.js +38 -0
  82. package/dist/tools/create.js +285 -0
  83. package/dist/tools/data-preview.js +37 -0
  84. package/dist/tools/delete.js +45 -0
  85. package/dist/tools/deploy-bsp.js +298 -0
  86. package/dist/tools/discovery.js +59 -0
  87. package/dist/tools/element-info.js +93 -0
  88. package/dist/tools/enhancements.js +186 -0
  89. package/dist/tools/extract-method.js +44 -0
  90. package/dist/tools/function-group.js +59 -0
  91. package/dist/tools/knowledge.js +275 -0
  92. package/dist/tools/lock-object.js +75 -0
  93. package/dist/tools/message-class.js +67 -0
  94. package/dist/tools/navigate.js +80 -0
  95. package/dist/tools/number-range.js +57 -0
  96. package/dist/tools/object-documentation.js +43 -0
  97. package/dist/tools/object-structure.js +78 -0
  98. package/dist/tools/object-versions.js +57 -0
  99. package/dist/tools/package-contents.js +60 -0
  100. package/dist/tools/pretty-printer.js +35 -0
  101. package/dist/tools/publish-binding.js +49 -0
  102. package/dist/tools/quick-fix.js +69 -0
  103. package/dist/tools/read.js +172 -0
  104. package/dist/tools/refactor-rename.js +60 -0
  105. package/dist/tools/release-transport.js +24 -0
  106. package/dist/tools/released-apis.js +51 -0
  107. package/dist/tools/repository-tree.js +90 -0
  108. package/dist/tools/scaffold-rap.js +642 -0
  109. package/dist/tools/search.js +73 -0
  110. package/dist/tools/shared/data-format.js +101 -0
  111. package/dist/tools/sql-console.js +17 -0
  112. package/dist/tools/system-info.js +271 -0
  113. package/dist/tools/traces.js +66 -0
  114. package/dist/tools/transport-contents.js +83 -0
  115. package/dist/tools/transports.js +68 -0
  116. package/dist/tools/unit-test.js +135 -0
  117. package/dist/tools/where-used.js +59 -0
  118. package/dist/tools/write.js +120 -0
  119. package/package.json +50 -0
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * Security Audit Log — registro de operações de segurança.
4
+ *
5
+ * Registra todas as operações WRITE, CREATE, DESTRUCTIVE e ADMIN,
6
+ * incluindo tentativas bloqueadas pela security policy.
7
+ * Separado do logger de chamadas ADT — este é focado em governança.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.auditLog = auditLog;
11
+ exports.auditAllowed = auditAllowed;
12
+ exports.auditBlocked = auditBlocked;
13
+ exports.getSessionAudit = getSessionAudit;
14
+ exports.getAuditSummary = getAuditSummary;
15
+ exports.readTodayAudit = readTodayAudit;
16
+ const fs_1 = require("fs");
17
+ const path_1 = require("path");
18
+ // ─── Config ───────────────────────────────────────────────────────
19
+ const AUDIT_DIR = process.env.ABAP_AI_AUDIT_DIR || (0, path_1.join)(process.env.HOME || "~", ".abap-ai", "audit");
20
+ const AUDIT_ENABLED = process.env.ABAP_AI_AUDIT !== "false";
21
+ // ─── Estado da sessão ─────────────────────────────────────────────
22
+ const sessionAuditEntries = [];
23
+ // ─── Funções ──────────────────────────────────────────────────────
24
+ function ensureAuditDir() {
25
+ if (!(0, fs_1.existsSync)(AUDIT_DIR)) {
26
+ (0, fs_1.mkdirSync)(AUDIT_DIR, { recursive: true });
27
+ }
28
+ }
29
+ function auditFileName() {
30
+ const date = new Date().toISOString().slice(0, 10);
31
+ return (0, path_1.join)(AUDIT_DIR, `security-${date}.jsonl`);
32
+ }
33
+ /**
34
+ * Extrai o hostname do SAP_URL para identificar o sistema no audit.
35
+ */
36
+ function getSystemId() {
37
+ const url = process.env.SAP_URL || "unknown";
38
+ try {
39
+ return new URL(url).hostname;
40
+ }
41
+ catch {
42
+ return url;
43
+ }
44
+ }
45
+ /**
46
+ * Registra uma entrada no audit log de segurança.
47
+ */
48
+ function auditLog(entry) {
49
+ const fullEntry = {
50
+ timestamp: new Date().toISOString(),
51
+ system: getSystemId(),
52
+ user: process.env.SAP_USER || "unknown",
53
+ ...entry,
54
+ };
55
+ sessionAuditEntries.push(fullEntry);
56
+ if (!AUDIT_ENABLED)
57
+ return;
58
+ try {
59
+ ensureAuditDir();
60
+ (0, fs_1.appendFileSync)(auditFileName(), JSON.stringify(fullEntry) + "\n", "utf-8");
61
+ }
62
+ catch {
63
+ // Audit silencioso — não deve quebrar operações
64
+ }
65
+ }
66
+ /**
67
+ * Atalho para registrar uma operação permitida.
68
+ */
69
+ function auditAllowed(tool, riskLevel, environment, params) {
70
+ auditLog({
71
+ tool,
72
+ risk_level: riskLevel,
73
+ environment,
74
+ result: "ALLOWED",
75
+ params,
76
+ });
77
+ }
78
+ /**
79
+ * Atalho para registrar uma operação bloqueada.
80
+ */
81
+ function auditBlocked(tool, riskLevel, environment, reason, params) {
82
+ auditLog({
83
+ tool,
84
+ risk_level: riskLevel,
85
+ environment,
86
+ result: "BLOCKED",
87
+ reason,
88
+ params,
89
+ });
90
+ }
91
+ /**
92
+ * Retorna as entradas de audit da sessão atual.
93
+ */
94
+ function getSessionAudit() {
95
+ return [...sessionAuditEntries];
96
+ }
97
+ /**
98
+ * Retorna resumo do audit da sessão para exibição.
99
+ */
100
+ function getAuditSummary() {
101
+ const allowed = sessionAuditEntries.filter((e) => e.result === "ALLOWED").length;
102
+ const blocked = sessionAuditEntries.filter((e) => e.result === "BLOCKED").length;
103
+ const byTool = {};
104
+ for (const entry of sessionAuditEntries) {
105
+ if (!byTool[entry.tool])
106
+ byTool[entry.tool] = { allowed: 0, blocked: 0 };
107
+ if (entry.result === "ALLOWED")
108
+ byTool[entry.tool].allowed++;
109
+ else
110
+ byTool[entry.tool].blocked++;
111
+ }
112
+ return {
113
+ total: sessionAuditEntries.length,
114
+ allowed,
115
+ blocked,
116
+ by_tool: byTool,
117
+ };
118
+ }
119
+ /**
120
+ * Lê o audit log do dia atual.
121
+ */
122
+ function readTodayAudit() {
123
+ try {
124
+ const file = auditFileName();
125
+ if (!(0, fs_1.existsSync)(file))
126
+ return [];
127
+ const content = (0, fs_1.readFileSync)(file, "utf-8");
128
+ return content
129
+ .split("\n")
130
+ .filter((line) => line.trim())
131
+ .map((line) => JSON.parse(line));
132
+ }
133
+ catch {
134
+ return [];
135
+ }
136
+ }
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+ /**
3
+ * Security Policy — controle de acesso por camada de ambiente SAP.
4
+ *
5
+ * Implementa o princípio: "O LKPABAP.ai NUNCA sobrepõe as restrições de
6
+ * segurança do SAP. Em PRD, só leitura. Em QAS, leitura + debug.
7
+ * Em DEV, tudo liberado. abap_release_transport sempre bloqueado."
8
+ *
9
+ * A autorização de dados (S_TADIR, S_DEVELOP, etc.) é 100% delegada ao SAP.
10
+ * Esta camada controla quais CATEGORIAS de operação o MCP server aceita executar.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getToolRisk = getToolRisk;
14
+ exports.loadPolicy = loadPolicy;
15
+ exports.checkToolAccess = checkToolAccess;
16
+ exports.getEffectiveMaxRows = getEffectiveMaxRows;
17
+ exports.checkTransportRequired = checkTransportRequired;
18
+ exports.getPolicy = getPolicy;
19
+ exports.setPolicy = setPolicy;
20
+ exports.getDefaultPolicy = getDefaultPolicy;
21
+ exports.listEnvironmentRoles = listEnvironmentRoles;
22
+ const fs_1 = require("fs");
23
+ const path_1 = require("path");
24
+ /**
25
+ * Mapa de cada tool para seu nível de risco.
26
+ * Tools não listadas aqui são consideradas READ (safe by default).
27
+ */
28
+ const TOOL_RISK = {
29
+ // READ — sem guard extra (default para tools não listadas)
30
+ abap_read: "READ",
31
+ abap_search: "READ",
32
+ abap_where_used: "READ",
33
+ abap_check: "READ",
34
+ abap_object_structure: "READ",
35
+ abap_data_preview: "READ",
36
+ abap_sql_console: "READ",
37
+ abap_element_info: "READ",
38
+ abap_pretty_printer: "READ",
39
+ abap_unit_test: "READ",
40
+ abap_atc_check: "READ",
41
+ abap_package_contents: "READ",
42
+ abap_object_versions: "READ",
43
+ abap_function_group: "READ",
44
+ abap_message_class: "READ",
45
+ abap_doc: "READ",
46
+ abap_code_completion: "READ",
47
+ abap_navigate: "READ",
48
+ abap_call_hierarchy: "READ",
49
+ abap_code_coverage: "READ",
50
+ abap_transport_contents: "READ",
51
+ abap_cds_annotations: "READ",
52
+ abap_cds_dependencies: "READ",
53
+ abap_annotation_propagation: "READ",
54
+ abap_enhancement_spot: "READ",
55
+ abap_lock_object: "READ",
56
+ abap_auth_object: "READ",
57
+ abap_number_range: "READ",
58
+ abap_repository_tree: "READ",
59
+ abap_discovery: "READ",
60
+ abap_released_apis: "READ",
61
+ abap_object_documentation: "READ",
62
+ abap_system_info: "READ",
63
+ abap_list_transports: "READ",
64
+ abap_knowledge: "READ",
65
+ abap_traces: "READ",
66
+ abap_breakpoints: "READ",
67
+ abapgit_repos: "READ",
68
+ // WRITE — modifica objetos existentes
69
+ abap_write: "WRITE",
70
+ abap_activate: "WRITE",
71
+ abap_refactor_rename: "WRITE",
72
+ abap_extract_method: "WRITE",
73
+ abap_quick_fix: "WRITE",
74
+ abap_publish_binding: "WRITE",
75
+ abap_deploy_bsp: "WRITE",
76
+ abap_assign_transport: "WRITE",
77
+ abapgit_pull: "WRITE",
78
+ abapgit_stage: "WRITE",
79
+ // CREATE — cria objetos novos no SAP
80
+ abap_create: "CREATE",
81
+ abap_create_transport: "CREATE",
82
+ abap_create_dcl: "CREATE",
83
+ abap_create_amdp: "CREATE",
84
+ abap_scaffold_rap: "CREATE",
85
+ // WRITE — delete segue a mesma regra de escrita (permitido em DEV, bloqueado em QAS/PRD)
86
+ abap_delete: "WRITE",
87
+ // ADMIN — operações administrativas de alto impacto (sempre bloqueado)
88
+ abap_release_transport: "ADMIN",
89
+ };
90
+ /**
91
+ * Retorna o nível de risco de uma tool.
92
+ */
93
+ function getToolRisk(toolName) {
94
+ return TOOL_RISK[toolName] ?? "READ";
95
+ }
96
+ // ─── Policies padrão por ambiente ─────────────────────────────────
97
+ const POLICY_DEVELOPMENT = {
98
+ environment_role: "DEVELOPMENT",
99
+ allowed_levels: ["READ", "WRITE", "CREATE"],
100
+ always_blocked: ["abap_release_transport"],
101
+ require_transport: false,
102
+ max_preview_rows: 0,
103
+ };
104
+ const POLICY_QUALITY = {
105
+ environment_role: "QUALITY",
106
+ allowed_levels: ["READ"],
107
+ always_blocked: [
108
+ "abap_release_transport",
109
+ "abap_delete",
110
+ "abap_scaffold_rap",
111
+ "abap_create",
112
+ "abap_create_dcl",
113
+ "abap_create_amdp",
114
+ "abap_write",
115
+ "abap_activate",
116
+ "abap_refactor_rename",
117
+ "abap_extract_method",
118
+ "abap_quick_fix",
119
+ "abap_publish_binding",
120
+ "abap_deploy_bsp",
121
+ "abapgit_pull",
122
+ ],
123
+ require_transport: true,
124
+ max_preview_rows: 100,
125
+ };
126
+ const POLICY_PRODUCTION = {
127
+ environment_role: "PRODUCTION",
128
+ allowed_levels: ["READ"],
129
+ always_blocked: [
130
+ "abap_release_transport",
131
+ "abap_delete",
132
+ "abap_scaffold_rap",
133
+ "abap_create",
134
+ "abap_create_dcl",
135
+ "abap_create_amdp",
136
+ "abap_create_transport",
137
+ "abap_write",
138
+ "abap_activate",
139
+ "abap_refactor_rename",
140
+ "abap_extract_method",
141
+ "abap_quick_fix",
142
+ "abap_publish_binding",
143
+ "abap_deploy_bsp",
144
+ "abapgit_pull",
145
+ "abapgit_stage",
146
+ "abap_assign_transport",
147
+ ],
148
+ require_transport: true,
149
+ max_preview_rows: 50,
150
+ };
151
+ const DEFAULT_POLICIES = {
152
+ DEVELOPMENT: POLICY_DEVELOPMENT,
153
+ QUALITY: POLICY_QUALITY,
154
+ PRODUCTION: POLICY_PRODUCTION,
155
+ };
156
+ // ─── Carregamento da policy ───────────────────────────────────────
157
+ /**
158
+ * Caminho do arquivo de policy central (planos Enterprise/Corporate).
159
+ * Gestores podem travar a policy criando este arquivo.
160
+ */
161
+ const CENTRAL_POLICY_PATH = (0, path_1.join)(process.env.HOME || "~", ".abap-ai", "security-policy.json");
162
+ /**
163
+ * Carrega a policy do ambiente a partir de:
164
+ * 1. Variável de ambiente ABAP_AI_SECURITY_POLICY (JSON inline)
165
+ * 2. Arquivo central ~/.abap-ai/security-policy.json (Enterprise/Corporate)
166
+ * 3. Variável ABAP_AI_ENV_ROLE (DEVELOPMENT | QUALITY | PRODUCTION)
167
+ * 4. Default: DEVELOPMENT
168
+ */
169
+ function loadPolicy() {
170
+ // 1. JSON inline (env var)
171
+ const policyJson = process.env.ABAP_AI_SECURITY_POLICY;
172
+ if (policyJson) {
173
+ try {
174
+ const parsed = JSON.parse(policyJson);
175
+ return mergeWithDefault(parsed);
176
+ }
177
+ catch {
178
+ // fallthrough
179
+ }
180
+ }
181
+ // 2. Arquivo central (gestores Enterprise/Corporate)
182
+ if ((0, fs_1.existsSync)(CENTRAL_POLICY_PATH)) {
183
+ try {
184
+ const raw = (0, fs_1.readFileSync)(CENTRAL_POLICY_PATH, "utf-8");
185
+ const parsed = JSON.parse(raw);
186
+ return mergeWithDefault(parsed);
187
+ }
188
+ catch {
189
+ // fallthrough
190
+ }
191
+ }
192
+ // 3. Env role simples
193
+ const envRole = (process.env.ABAP_AI_ENV_ROLE || "").toUpperCase();
194
+ if (DEFAULT_POLICIES[envRole]) {
195
+ return deepClone(DEFAULT_POLICIES[envRole]);
196
+ }
197
+ // 4. Default: DEVELOPMENT
198
+ return deepClone(POLICY_DEVELOPMENT);
199
+ }
200
+ /**
201
+ * Verifica se uma tool pode ser executada sob a policy atual.
202
+ */
203
+ function checkToolAccess(toolName, policy) {
204
+ // 1. abap_release_transport — SEMPRE bloqueado, independente de qualquer config
205
+ if (toolName === "abap_release_transport") {
206
+ return {
207
+ allowed: false,
208
+ reason: `BLOQUEADO: abap_release_transport é sempre bloqueado pelo LKPABAP.ai. `
209
+ + `Liberar transportes é uma operação irreversível que pode propagar mudanças para ambientes produtivos. `
210
+ + `Execute esta operação manualmente na transação SE09/SE10 do SAP GUI.`,
211
+ };
212
+ }
213
+ // 2. Tool na lista de always_blocked
214
+ if (policy.always_blocked.includes(toolName)) {
215
+ return {
216
+ allowed: false,
217
+ reason: `BLOQUEADO: A tool "${toolName}" não é permitida no ambiente ${policy.environment_role}. `
218
+ + `Esta restrição é definida pela política de segurança do sistema. `
219
+ + describeEnvironmentRestriction(policy.environment_role),
220
+ };
221
+ }
222
+ // 3. Nível de risco da tool vs níveis permitidos
223
+ const riskLevel = getToolRisk(toolName);
224
+ if (!policy.allowed_levels.includes(riskLevel)) {
225
+ return {
226
+ allowed: false,
227
+ reason: `BLOQUEADO: A tool "${toolName}" requer nível "${riskLevel}", `
228
+ + `mas o ambiente ${policy.environment_role} só permite: ${policy.allowed_levels.join(", ")}. `
229
+ + describeEnvironmentRestriction(policy.environment_role),
230
+ };
231
+ }
232
+ return { allowed: true };
233
+ }
234
+ /**
235
+ * Retorna o limite de rows para preview/sql considerando a policy.
236
+ * Se a policy define um limite, usa o menor entre o limite da policy e o solicitado.
237
+ */
238
+ function getEffectiveMaxRows(requestedRows, policy) {
239
+ if (policy.max_preview_rows <= 0)
240
+ return requestedRows;
241
+ return Math.min(requestedRows, policy.max_preview_rows);
242
+ }
243
+ /**
244
+ * Verifica se transport request é obrigatório e não foi fornecido.
245
+ */
246
+ function checkTransportRequired(toolName, transportRequest, policy) {
247
+ const riskLevel = getToolRisk(toolName);
248
+ if (policy.require_transport
249
+ && (riskLevel === "WRITE" || riskLevel === "CREATE")
250
+ && !transportRequest) {
251
+ return {
252
+ allowed: false,
253
+ reason: `BLOQUEADO: O ambiente ${policy.environment_role} exige transport request para operações de ${riskLevel}. `
254
+ + `Informe o parâmetro transport_request (ex: "DEVK900123"). `
255
+ + `Use abap_list_transports ou abap_create_transport para obter um.`,
256
+ };
257
+ }
258
+ return { allowed: true };
259
+ }
260
+ // ─── Singleton ────────────────────────────────────────────────────
261
+ let currentPolicy = null;
262
+ /**
263
+ * Retorna a policy atual. Carrega do ambiente/arquivo na primeira chamada.
264
+ */
265
+ function getPolicy() {
266
+ if (!currentPolicy) {
267
+ currentPolicy = loadPolicy();
268
+ }
269
+ return currentPolicy;
270
+ }
271
+ /**
272
+ * Força uma policy específica (usado em testes ou override programático).
273
+ */
274
+ function setPolicy(policy) {
275
+ currentPolicy = policy;
276
+ }
277
+ /**
278
+ * Retorna a policy padrão para um environment role.
279
+ */
280
+ function getDefaultPolicy(role) {
281
+ return deepClone(DEFAULT_POLICIES[role] || POLICY_DEVELOPMENT);
282
+ }
283
+ /**
284
+ * Lista os environment roles disponíveis.
285
+ */
286
+ function listEnvironmentRoles() {
287
+ return ["DEVELOPMENT", "QUALITY", "PRODUCTION"];
288
+ }
289
+ // ─── Helpers ──────────────────────────────────────────────────────
290
+ function describeEnvironmentRestriction(role) {
291
+ switch (role) {
292
+ case "PRODUCTION":
293
+ return "Em ambientes PRODUTIVOS, o LKPABAP.ai opera somente em modo leitura. "
294
+ + "Qualquer modificação deve ser feita via transporte a partir do ambiente de desenvolvimento.";
295
+ case "QUALITY":
296
+ return "Em ambientes de QUALIDADE (QAS), o LKPABAP.ai opera somente em modo leitura. "
297
+ + "Modificações devem ser transportadas a partir do ambiente de desenvolvimento.";
298
+ case "DEVELOPMENT":
299
+ return ""; // DEV não tem restrição descritiva
300
+ default:
301
+ return "";
302
+ }
303
+ }
304
+ function mergeWithDefault(partial) {
305
+ const role = partial.environment_role || "DEVELOPMENT";
306
+ const base = deepClone(DEFAULT_POLICIES[role] || POLICY_DEVELOPMENT);
307
+ return {
308
+ environment_role: partial.environment_role ?? base.environment_role,
309
+ allowed_levels: partial.allowed_levels ?? base.allowed_levels,
310
+ always_blocked: [
311
+ ...new Set([
312
+ ...base.always_blocked,
313
+ ...(partial.always_blocked ?? []),
314
+ ]),
315
+ ],
316
+ require_transport: partial.require_transport ?? base.require_transport,
317
+ max_preview_rows: partial.max_preview_rows ?? base.max_preview_rows,
318
+ };
319
+ }
320
+ function deepClone(obj) {
321
+ return JSON.parse(JSON.stringify(obj));
322
+ }
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ /**
3
+ * System Profile — configuração contextual do sistema SAP alvo.
4
+ *
5
+ * Permite ao MCP adaptar comportamento (URLs, CDS syntax, ETag handling, etc.)
6
+ * com base no tipo e versão do sistema conectado.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.getProfile = getProfile;
10
+ exports.setProfile = setProfile;
11
+ exports.getPreset = getPreset;
12
+ exports.listPresets = listPresets;
13
+ exports.resolveODataV4Url = resolveODataV4Url;
14
+ exports.resolveBspUrl = resolveBspUrl;
15
+ // ─── Presets ──────────────────────────────────────────────────────
16
+ const ON_PREMISE_S4_DEFAULTS = {
17
+ system: {
18
+ type: "ON_PREMISE_S4",
19
+ release: "2023",
20
+ abapPlatform: "STANDARD",
21
+ sapBasisVersion: "758",
22
+ systemId: "",
23
+ },
24
+ capabilities: {
25
+ cdsViewEntity: true,
26
+ cdsProjection: true,
27
+ rapManaged: true,
28
+ rapDraftEnabled: true,
29
+ releasedApiOnly: false,
30
+ codeCompletion: true,
31
+ callHierarchy: true,
32
+ quickFix: true,
33
+ extractMethod: true,
34
+ codeCoverage: true,
35
+ sqlConsole: true,
36
+ releasedApiCatalog: true,
37
+ abapGitAvailable: false,
38
+ },
39
+ gateway: {
40
+ topology: "EMBEDDED",
41
+ odataV4UrlPattern: "/sap/opu/odata4/sap/{binding}/srvd/sap/{binding}/{version}/",
42
+ publishEndpoint: "/sap/bc/adt/businessservices/odatav4/publishjobs",
43
+ autoRegistration: false,
44
+ },
45
+ client: {
46
+ role: "DEVELOPMENT",
47
+ allowLocalPublish: true,
48
+ },
49
+ ui5: {
50
+ bootstrapPath: "/sap/public/bc/ui5_ui5/resources/",
51
+ bspUrlPattern: "/sap/bc/ui5_ui5/sap/{bsp}?sap-client={client}",
52
+ },
53
+ quirks: {
54
+ etagRequiresManualFix: true,
55
+ conversionExitFields: ["USTYP", "BSTYP", "PRCTR", "KOSTL"],
56
+ lockReturns406ForDDLS: true,
57
+ },
58
+ };
59
+ const BTP_ABAP_ENV_DEFAULTS = {
60
+ system: {
61
+ type: "BTP_ABAP_ENV",
62
+ release: "2023",
63
+ abapPlatform: "CLOUD",
64
+ sapBasisVersion: "758",
65
+ systemId: "",
66
+ },
67
+ capabilities: {
68
+ cdsViewEntity: true,
69
+ cdsProjection: true,
70
+ rapManaged: true,
71
+ rapDraftEnabled: true,
72
+ releasedApiOnly: true,
73
+ codeCompletion: true,
74
+ callHierarchy: true,
75
+ quickFix: true,
76
+ extractMethod: true,
77
+ codeCoverage: true,
78
+ sqlConsole: true,
79
+ releasedApiCatalog: true,
80
+ abapGitAvailable: false,
81
+ },
82
+ gateway: {
83
+ topology: "EMBEDDED",
84
+ odataV4UrlPattern: "/sap/opu/odata4/sap/{binding}/{version}/",
85
+ publishEndpoint: "",
86
+ autoRegistration: true,
87
+ },
88
+ client: {
89
+ role: "DEVELOPMENT",
90
+ allowLocalPublish: true,
91
+ },
92
+ ui5: {
93
+ bootstrapPath: "/resources/",
94
+ bspUrlPattern: "",
95
+ },
96
+ quirks: {
97
+ etagRequiresManualFix: false,
98
+ conversionExitFields: [],
99
+ lockReturns406ForDDLS: false,
100
+ },
101
+ };
102
+ const ON_PREMISE_ECC_DEFAULTS = {
103
+ system: {
104
+ type: "ON_PREMISE_ECC",
105
+ release: "750",
106
+ abapPlatform: "STANDARD",
107
+ sapBasisVersion: "750",
108
+ systemId: "",
109
+ },
110
+ capabilities: {
111
+ cdsViewEntity: false, // ECC não tem view entity
112
+ cdsProjection: false,
113
+ rapManaged: false,
114
+ rapDraftEnabled: false,
115
+ releasedApiOnly: false,
116
+ codeCompletion: true, // disponível desde BASIS 750
117
+ callHierarchy: false,
118
+ quickFix: false,
119
+ extractMethod: false,
120
+ codeCoverage: false,
121
+ sqlConsole: false,
122
+ releasedApiCatalog: false,
123
+ abapGitAvailable: false,
124
+ },
125
+ gateway: {
126
+ topology: "HUB",
127
+ odataV4UrlPattern: "", // ECC geralmente não tem OData V4
128
+ publishEndpoint: "",
129
+ autoRegistration: false,
130
+ },
131
+ client: {
132
+ role: "DEVELOPMENT",
133
+ allowLocalPublish: false,
134
+ },
135
+ ui5: {
136
+ bootstrapPath: "/sap/public/bc/ui5_ui5/resources/",
137
+ bspUrlPattern: "/sap/bc/ui5_ui5/sap/{bsp}?sap-client={client}",
138
+ },
139
+ quirks: {
140
+ etagRequiresManualFix: false,
141
+ conversionExitFields: [],
142
+ lockReturns406ForDDLS: false,
143
+ },
144
+ };
145
+ const PRESETS = {
146
+ ON_PREMISE_S4: ON_PREMISE_S4_DEFAULTS,
147
+ BTP_ABAP_ENV: BTP_ABAP_ENV_DEFAULTS,
148
+ ON_PREMISE_ECC: ON_PREMISE_ECC_DEFAULTS,
149
+ };
150
+ // ─── Profile singleton ───────────────────────────────────────────
151
+ let currentProfile = null;
152
+ /**
153
+ * Retorna o profile atual. Se não inicializado, usa o preset
154
+ * definido em SAP_SYSTEM_TYPE ou detecta automaticamente.
155
+ */
156
+ function getProfile() {
157
+ if (!currentProfile) {
158
+ const preset = process.env.SAP_SYSTEM_TYPE || "ON_PREMISE_S4";
159
+ currentProfile = deepClone(PRESETS[preset] || ON_PREMISE_S4_DEFAULTS);
160
+ }
161
+ return currentProfile;
162
+ }
163
+ /**
164
+ * Define o profile (usado pelo abap_system_info após auto-detecção).
165
+ */
166
+ function setProfile(profile) {
167
+ currentProfile = profile;
168
+ }
169
+ /**
170
+ * Retorna um preset base pelo nome.
171
+ */
172
+ function getPreset(name) {
173
+ const p = PRESETS[name];
174
+ return p ? deepClone(p) : undefined;
175
+ }
176
+ /**
177
+ * Lista os presets disponíveis.
178
+ */
179
+ function listPresets() {
180
+ return Object.keys(PRESETS);
181
+ }
182
+ /**
183
+ * Gera a URL real do serviço OData V4 com base no pattern do profile.
184
+ */
185
+ function resolveODataV4Url(bindingName, version = "0000") {
186
+ const profile = getProfile();
187
+ const pattern = profile.gateway.odataV4UrlPattern;
188
+ if (!pattern)
189
+ return "";
190
+ return pattern
191
+ .replace(/\{binding\}/g, bindingName.toLowerCase())
192
+ .replace(/\{version\}/g, version);
193
+ }
194
+ /**
195
+ * Gera a URL da app BSP com base no pattern do profile.
196
+ */
197
+ function resolveBspUrl(bspName) {
198
+ const profile = getProfile();
199
+ const client = process.env.SAP_CLIENT ?? "100";
200
+ return profile.ui5.bspUrlPattern
201
+ .replace("{bsp}", bspName.toLowerCase())
202
+ .replace("{client}", client);
203
+ }
204
+ // ─── Helpers ─────────────────────────────────────────────────────
205
+ function deepClone(obj) {
206
+ return JSON.parse(JSON.stringify(obj));
207
+ }