Skip to content

Add 2nd gen AI Logic sensitive data redaction sample - #1315

Open
jhuleatt wants to merge 1 commit into
mainfrom
ai-logic-triggers
Open

jhuleatt wants to merge 1 commit into
mainfrom
ai-logic-triggers

Conversation

@jhuleatt

Copy link
Copy Markdown
Contributor

Description

Adds a 2nd gen Firebase Functions sample in Node/ai-logic-sensitive-data demonstrating how to intercept and redact sensitive data (PII) using Firebase AI Logic triggers (beforeGenerateContent and afterGenerateContent) and Cloud Sensitive Data Protection (DLP).

Key Features

  • Pre-request trigger (redactPrompt): Intercepts beforeGenerateContent requests and redacts sensitive data (emails, phone numbers, credit card numbers, SSNs) from prompt contents and system instructions before reaching the Gemini API.
  • Post-request trigger (redactResponse): Intercepts afterGenerateContent responses and inspects/redacts sensitive data generated by the model before returning to the client.
  • DLP Redaction helper: Uses @google-cloud/dlp deidentifyContent with replaceWithInfoTypeConfig.
  • Documentation Snippets: Formatted with DevSite includecode region tags:
    • ai_logic_imports
    • ai_logic_redact_helper
    • ai_logic_before_generate_content
    • ai_logic_after_generate_content
    • ai_logic_pre_request
    • ai_logic_sensitive_data_all
  • Tests & Linting: 30 unit tests using Node built-in test runner (node --test), ESLint passing, and zero type errors.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new Node.js sample demonstrating how to use Firebase AI Logic triggers with Cloud Sensitive Data Protection (DLP) to redact sensitive data from prompts and model responses. Feedback suggests improving code quality by avoiding global ESLint rule disables and optimizing performance by caching the projectId promise globally rather than fetching it on every function invocation.

Comment on lines +4 to +14
rules: {
"no-console": "off",
"no-unused-vars": "off",
"no-undef": "off",
"no-empty": "off",
"no-useless-escape": "off",
"no-prototype-builtins": "off",
"no-redeclare": "off",
"no-constant-condition": "off",
"no-case-declarations": "off"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Disabling a large number of important ESLint rules globally is not recommended as it can hide potential bugs and reduces code quality. While this might be acceptable for a simple sample, it's better to be more selective. For example, no-unused-vars and no-undef can catch critical errors.

Consider removing these global disables. If specific lines of code need to bypass a rule, use inline comments like // eslint-disable-next-line <rule-name> for those specific cases. This makes exceptions explicit and maintains a higher standard of code quality for the rest of the project.

Comment on lines +29 to +45
let dlp = new DlpServiceClient();

/**
* Redacts sensitive data from a text string using Cloud Sensitive Data Protection (DLP).
*
* Inspects for basic sensitive infoTypes (email, phone number, credit card number, SSN)
* and replaces detected values with their infoType placeholder (e.g. "[EMAIL_ADDRESS]").
*
* @param {string} text - The raw input text string to inspect and redact.
* @returns {Promise<string>} The redacted text, or the original text if empty or unchanged.
*/
export async function redactSensitiveData(text) {
if (typeof text !== "string" || !text.trim()) {
return text;
}

const projectId = await dlp.getProjectId();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better performance, the projectId should be fetched only once during a cold start, not on every function invocation. The projectId for a given function deployment will not change. You can initialize the promise to get the project ID in the global scope and then await it inside the function.

let dlp = new DlpServiceClient();

// Initialize the projectId promise once in the global scope.
const projectIdPromise = dlp.getProjectId();

/**
 * Redacts sensitive data from a text string using Cloud Sensitive Data Protection (DLP).
 *
 * Inspects for basic sensitive infoTypes (email, phone number, credit card number, SSN)
 * and replaces detected values with their infoType placeholder (e.g. "[EMAIL_ADDRESS]").
 *
 * @param {string} text - The raw input text string to inspect and redact.
 * @returns {Promise<string>} The redacted text, or the original text if empty or unchanged.
 */
export async function redactSensitiveData(text) {
  if (typeof text !== "string" || !text.trim()) {
    return text;
  }

  const projectId = await projectIdPromise;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant