Segurança & Integrações — JavaScript / TypeScript
Índice
Segurança
SecurityPolicy
typescript
import {
SecurityPolicy,
defaultPolicy,
mergePolicy,
STRICT_POLICY,
PERMISSIVE_POLICY,
setGlobalPolicy,
clearGlobalPolicy,
getGlobalPolicy,
} from "@safe-access-inline/safe-access-inline";
const policy: SecurityPolicy = mergePolicy(defaultPolicy, {
maxDepth: 128,
maxPayloadBytes: 1_048_576,
allowedDirs: ["/app/config"],
url: { allowedHosts: ["api.example.com"] },
csvMode: "strip",
maskPatterns: ["password", /.*_token/],
});
// Carregar com política
const accessor = SafeAccess.withPolicy(jsonString, policy);
const fromFile = SafeAccess.fromFileWithPolicy("/app/config.json", policy);
const fromUrl = await SafeAccess.fromUrlWithPolicy(
"https://api.example.com/config.json",
policy,
);Presets de Política
Dois presets integrados estão disponíveis:
STRICT_POLICY— limites restritivos para entrada não confiávelPERMISSIVE_POLICY— limites relaxados para ambientes confiáveis
typescript
const accessor = SafeAccess.withPolicy(data, STRICT_POLICY);Política Global
Defina uma política global que se aplica como padrão para todas as operações:
typescript
setGlobalPolicy(STRICT_POLICY);
const current = getGlobalPolicy(); // SecurityPolicy | undefined
clearGlobalPolicy();
// Ou via facade SafeAccess
SafeAccess.setGlobalPolicy(STRICT_POLICY);
SafeAccess.clearGlobalPolicy();Mascaramento de dados
typescript
const accessor = SafeAccess.fromObject({
user: "Ana",
password: "s3cret",
api_key: "abc-123",
});
const safe = accessor.masked();
safe.get("password"); // '[REDACTED]'
safe.get("api_key"); // '[REDACTED]'
safe.get("user"); // 'Ana'
// Padrões customizados
const custom = accessor.masked(["custom_secret", /.*_token/]);Readonly & Deep Freeze
typescript
// Readonly — lança ReadonlyViolationError ao tentar modificar
const ro = SafeAccess.fromObject({ key: "value" }, { readonly: true });
ro.get("key"); // 'value'
ro.set("key", "new"); // lança ReadonlyViolationError
// Deep freeze — previne poluição de protótipo no objeto de dados
SafeAccess.deepFreeze(myObject);Validação de Schema
typescript
import { SchemaRegistry } from "@safe-access-inline/safe-access-inline";
// Registrar um adapter padrão (implemente SchemaAdapterInterface)
SchemaRegistry.setDefaultAdapter(myAdapter);
// Validar — lança SchemaValidationError em caso de falha
accessor.validate(schema);
// Encadeamento fluente
const name = accessor.validate(schema).get("name");Log de Auditoria
typescript
const unsub = SafeAccess.onAudit((event) => {
// event = { type: 'file.read', timestamp: 1234567890.123, detail: {...} }
console.log(event.type, event.detail);
});
// Eventos: file.read, file.watch, url.fetch, security.violation,
// security.deprecation, data.mask, data.freeze, schema.validate
// Limpar
unsub();
SafeAccess.clearAuditListeners();Integrações de Framework
NestJS
typescript
import {
SafeAccessModule,
SAFE_ACCESS,
} from "@safe-access-inline/safe-access-inline";
// No seu módulo NestJS
@Module({
imports: [
SafeAccessModule.register({
filePath: "./config.yaml",
allowedDirs: ["./config"],
}),
],
})
export class AppModule {}
// Injetar em um serviço
@Injectable()
export class ConfigService {
constructor(@Inject(SAFE_ACCESS) private config: AbstractAccessor) {}
getDbHost() {
return this.config.get("database.host");
}
}Vite
typescript
import {
safeAccessPlugin,
loadConfig,
} from "@safe-access-inline/safe-access-inline";
// vite.config.ts
export default defineConfig({
plugins: [
safeAccessPlugin({
files: ["./config/defaults.yaml", "./config/local.yaml"],
virtualId: "virtual:app-config", // opcional, padrão é 'virtual:safe-access-config'
}),
],
});
// Na sua aplicação
import config from "virtual:app-config";
// config é um accessor mesclado de todos os arquivos
// Ou carregue a config manualmente
const config2 = loadConfig(["./config/defaults.yaml", "./config/local.yaml"]);